[
  {
    "path": ".DEREK.yml",
    "content": "maintainers:\n - evilsocket\n - caquino\n - justin-p\n \nfeatures:\n - comments\n - pr_description_required\n \n"
  },
  {
    "path": ".editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# editorconfig.org\n\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[Makefile]\nindent_style = tab\n\n[*.py]\nindent_style = space\nindent_size = 4\n\n[*.json]\ninsert_final_newline = ignore\n\n[*.js]\nindent_style = ignore\ninsert_final_newline = ignore\n\n[*.{md,txt}]\nindent_size = 4\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".gitattributes",
    "content": "/builder/** linguist-vendored\n/scripts/** linguist-vendored\n/pwnagotchi/ui/web/static/** linguist-vendored\n/pwnagotchi/ui/web/templates/*.* linguist-vendored\n/pwnagotchi/ui/web/templates/** linguist-vendored\n/pwnagotchi/locale/** linguist-vendored"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "evilsocket\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHubSponsors-enabled usernames e.g., [user1, user2]\npatreon: evilsocket\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"[BUG]\"\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. ...\n2. ...\n3. ...\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Environment (please complete the following information):**\n - Pwnagotchi version\n - OS version\n - Type of hardware\n - Any additional hardware used\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/other.md",
    "content": "---\nname: Other\nabout: Describe this issue template's purpose here.\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--- Provide a general summary of the issue in the Title above -->\n\n## Expected Behaviour\n<!--- If you're describing a bug, tell us what should happen -->\n<!--- If you're suggesting a change/improvement, tell us how it should work -->\n\n## Current Behaviour\n<!--- If describing a bug, tell us what happens instead of the expected behavior -->\n<!--- If suggesting a change/improvement, explain the difference from current behavior -->\n\n## Possible Solution\n<!--- Not obligatory, but suggest a fix/reason for the bug, -->\n<!--- or ideas how to implement the addition or change -->\n\n## Steps to Reproduce (for bugs)\n<!--- Provide a link to a live example, or an unambiguous set of steps to -->\n<!--- reproduce this bug. Include code to reproduce, if relevant -->\n1.\n2.\n3.\n4.\n\n## Context\n<!--- How has this issue affected you? What are you trying to accomplish? -->\n<!--- Providing context helps us come up with a solution that is most useful in the real world -->\n\n## Your Environment\n\n- [ ] You're using the official images\n\n- [ ] You're using a raspberry pi 0\n\n- [ ] You're using a supported LCD\n\n\n<!--- Include as many relevant details about the environment you experienced the bug in -->\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--- Provide a general summary of your changes in the Title above -->\n\n## Description\n<!--- Describe your changes in detail -->\n\n## Motivation and Context\n<!--- Why is this change required? What problem does it solve? -->\n<!--- If it fixes an open issue, please link to the issue here. -->\n- [ ] I have raised an issue to propose this change ([required](https://github.com/evilsocket/pwnagotchi/blob/master/CONTRIBUTING.md))\n\n\n## How Has This Been Tested?\n<!--- Please describe in detail how you tested your changes. -->\n<!--- Include details of your testing environment, and the tests you ran to -->\n<!--- see how your change affects other areas of the code, etc. -->\n\n## Types of changes\n<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would cause existing functionality to change)\n\n## Checklist:\n<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->\n<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->\n- [ ] My code follows the code style of this project.\n- [ ] My change requires a change to the documentation.\n- [ ] I have updated the documentation accordingly.\n- [ ] I've read the [CONTRIBUTION](https://github.com/evilsocket/pwnagotchi/blob/master/CONTRIBUTING.md) guide\n- [ ] I have signed-off my commits with `git commit -s`\n"
  },
  {
    "path": ".gitignore",
    "content": "*.img\n*.img.bmap\n*.pcap\n*.po~\npreview.png\n__pycache__\n_backups\n_emulation\n_utils\nconfig.laptop.yml\n.idea\npacker_cache\noutput-pwnagotchi\n.DS_Store\nbuild\ndist\npwnagotchi.egg-info\n*backup*.tgz\n*backup*.gz\n.vscode\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n"
  },
  {
    "path": ".travis.yml",
    "content": "dist: bionic\nlanguage: go\ngo:\n  - 1.x\nenv:\n  global:\n    - LANG=C\n    - LC_ALL=C\ndeploy:\n  provider: releases\n  api_key:\n      secure: \"Rj0QnEDv02UzjKaxHHxJ/Sdj50EOFIrsKShr27GtVNSwHmNKxQuwlh31T0DQdif4wzcDtUZ5XWxr85vLkKJt1L8anb7Tb63qlu7Da69C+upSUow1uJkjsiScbMPqwHpwDIkkcUIbPsdbowI7qiNhRBD7nF8yyLPC5YLiU0cXKuGh4+Q5xdIlL3P7p8jm0919Y+olglzAZj0iNR/QxGOb+laNH8xi0oUsIPi5V0ZFfO/W/sm+nks9ki5nolfd1ML1gcbOD7uKuxIMTUrpDLl4p2Jx9IVQW+G2/tkmNLbP5Ga65NxQcfABQDYY3tCD8PsmFK9PEwa4cMbGJjqlo3yR7P21J5Aj3rK+L4KDntOvwem3Z3Y/v2JlQZn+gelhNFCxuPBi3ZihSf7POMHtpAYmi13N2ruzOg1ayjeYph0iN3vXIPs67DpAPaxK+8L2yoo6Nr/Cago9pGTkZoqS+J0fnWT31NXoYREPgg//L2+m42twQirFXttbhlGTBgNMLXpwcm8bZ2DW3pu3AEgVUxSoNAOjudoeyC0VzA6nUqe6STmfk06OYqcwM8q8NEyD62iAvUYU3Q7FnauZqcBqcP+ZYx82NPZybrQRX6YlJck5UomHbbEfjgpDFT+WvjrrfICmXH29YBOL1LWR4cKMT6RY58Cv8hT2PYxomB2I+DRrbqU=\"\n  skip_cleanup: true\n  file_glob: true\n  file:\n    - pwnagotchi-*.zip\n    - pwnagotchi-*.sha256\n  on:\n    tags: true\n    repo: evilsocket/pwnagotchi\nbranches:\n  only:\n    - \"/^v[0-9]+\\\\.[0-9]+\\\\.[0-9]+[A-Za-z0-9]*$/\"\ncache:\n  apt: true\nbefore_script:\n  - sudo apt-get -y update || true\n  - sudo apt-get -y install qemu-system-arm qemu-user-static binfmt-support bmap-tools kpartx\n  - sudo update-binfmts --display\nscript:\n  - sudo make clean\n  - sudo -E env \"PATH=$PATH\" make install\n  - sudo make image -e PWN_HOSTNAME=pwnagotchi PWN_VERSION=$TRAVIS_TAG\nnotifications:\n  slack:\n    secure: aovN87lswg+TTLobxJpevC0p2F4omTAlsOzeKqLysRW55o5rRhRC1SgwRkWUl19yr49nsyffwmv/b7OcyQiWIVnz1bxxE9XOKP8zgRMA/bKKcyAcPktPqHXsALIQDseXyl0kz7fwdkRWg0UC2HpKqi5koAhmBYTX/fbzieyeHCbcQ7lbFfVFIepE1401y9m1IqUHcHuGfFhMvTaSDIpXrDXnWdA8+gDAl0HKJv41MIsgmffbh/QhD2jLBWzItjxFC3llmNfy88pnzCk0+HBMY/4272LXb0czX7et5HJeM74oxPqkb3aKXFxZgNaDl7cYdV+kzj9dfKUk47hAqwbxlirit5WvHI1Br1VyA90+PFvcC/p41J8gCv0IlcB5vjWN8NKWA1J+Y1F+KvrujMvGtgd0foHZvaSutuRODhI1cBh5rYAiLCroRSlvKMw3IJRyCRstYgUlMIJ3cI2Ova/kU44KtDVmjT9VE/pPkhkHBPvcYThL6skZTdl19E/RlormLu3XObG1aHLZ+Znxe/aL7tWHi0KMOlpy+TMDdps4go7URnJ8yitHtIvU/zMtBrztIwN0Oy2JLKXrS5qIijmRAkBLxe0NxuG01DYFzEO3KtnRirP4uSe3QcrjyP4sqPrVhrjl3TR6gwg8V1juvDXB4e2h8yCpaUW5AdSBOlx9riY=\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at pwnagotchi@gmail.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Contributing\n\n### Guidelines\n\nHere are a few guidelines for contributing:\n\n* If you would like to contribute to the codebase **please raise an issue to propose the change**\n* Do not mix feature changes or fixes with refactoring - it makes the code harder to review and means there is more for the maintainers (with limited time) to test\n\n* If you have found a bug please raise an issue and fill out the whole template.\n* If the documentation can be improved / translated etc please raise an issue to discuss.\n* Please always provide a summary of what you changed, how you did it and how it can be tested.\n\n### License\n\nThis project is licensed under the GPL3 License.\n\n#### Sign your work\n\nThe sign-off is a simple line at the end of the explanation for a patch. Your\nsignature certifies that you wrote the patch or otherwise have the right to pass\nit on as an open-source patch. The rules are pretty simple: if you can certify\nthe below (from [developercertificate.org](http://developercertificate.org/)):\n\n```\nDeveloper Certificate of Origin\nVersion 1.1\n\nCopyright (C) 2004, 2006 The Linux Foundation and its contributors.\n1 Letterman Drive\nSuite D4700\nSan Francisco, CA, 94129\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\nDeveloper's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n(a) The contribution was created in whole or in part by me and I\n    have the right to submit it under the open source license\n    indicated in the file; or\n\n(b) The contribution is based upon previous work that, to the best\n    of my knowledge, is covered under an appropriate open source\n    license and I have the right under that license to submit that\n    work with modifications, whether created in whole or in part\n    by me, under the same open source license (unless I am\n    permitted to submit under a different license), as indicated\n    in the file; or\n\n(c) The contribution was provided directly to me by some other\n    person who certified (a), (b) or (c) and I have not modified\n    it.\n\n(d) I understand and agree that this project and the contribution\n    are public and that a record of the contribution (including all\n    personal information I submit with it, including my sign-off) is\n    maintained indefinitely and may be redistributed consistent with\n    this project or the open source license(s) involved.\n```\n\nThen you just add a line to every git commit message:\n\n    Signed-off-by: Joe Smith <joe.smith@email.com>\n\nIf you set your `user.name` and `user.email` git configs, you can sign your\ncommit automatically with `git commit -s`.\n\n* Please sign your commits with `git commit -s` so that commits are traceable.\n"
  },
  {
    "path": "LICENSE.md",
    "content": "GNU GENERAL PUBLIC LICENSE\n==========================\n\nVersion 3, 29 June 2007\n\nCopyright &copy; 2007 Free Software Foundation, Inc. &lt;<https://www.fsf.org/>&gt;\n\nEveryone is permitted to copy and distribute verbatim copies of this license\ndocument, but changing it is not allowed.\n\n## Preamble\n\nThe GNU General Public License is a free, copyleft license for software and other\nkinds of works.\n\nThe licenses for most software and other practical works are designed to take away\nyour freedom to share and change the works. By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change all versions of a\nprogram--to make sure it remains free software for all its users. We, the Free\nSoftware Foundation, use the GNU General Public License for most of our software; it\napplies also to any other work released this way by its authors. You can apply it to\nyour programs, too.\n\nWhen we speak of free software, we are referring to freedom, not price. Our General\nPublic Licenses are designed to make sure that you have the freedom to distribute\ncopies of free software (and charge for them if you wish), that you receive source\ncode or can get it if you want it, that you can change the software or use pieces of\nit in new free programs, and that you know you can do these things.\n\nTo protect your rights, we need to prevent others from denying you these rights or\nasking you to surrender the rights. Therefore, you have certain responsibilities if\nyou distribute copies of the software, or if you modify it: responsibilities to\nrespect the freedom of others.\n\nFor example, if you distribute copies of such a program, whether gratis or for a fee,\nyou must pass on to the recipients the same freedoms that you received. You must make\nsure that they, too, receive or can get the source code. And you must show them these\nterms so they know their rights.\n\nDevelopers that use the GNU GPL protect your rights with two steps: (1) assert\ncopyright on the software, and (2) offer you this License giving you legal permission\nto copy, distribute and/or modify it.\n\nFor the developers' and authors' protection, the GPL clearly explains that there is\nno warranty for this free software. For both users' and authors' sake, the GPL\nrequires that modified versions be marked as changed, so that their problems will not\nbe attributed erroneously to authors of previous versions.\n\nSome devices are designed to deny users access to install or run modified versions of\nthe software inside them, although the manufacturer can do so. This is fundamentally\nincompatible with the aim of protecting users' freedom to change the software. The\nsystematic pattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable. Therefore, we have designed\nthis version of the GPL to prohibit the practice for those products. If such problems\narise substantially in other domains, we stand ready to extend this provision to\nthose domains in future versions of the GPL, as needed to protect the freedom of\nusers.\n\nFinally, every program is threatened constantly by software patents. States should\nnot allow patents to restrict development and use of software on general-purpose\ncomputers, but in those that do, we wish to avoid the special danger that patents\napplied to a free program could make it effectively proprietary. To prevent this, the\nGPL assures that patents cannot be used to render the program non-free.\n\nThe precise terms and conditions for copying, distribution and modification follow.\n\n## TERMS AND CONDITIONS\n\n### 0. Definitions.\n\n&ldquo;This License&rdquo; refers to version 3 of the GNU General Public License.\n\n&ldquo;Copyright&rdquo; also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n&ldquo;The Program&rdquo; refers to any copyrightable work licensed under this\nLicense. Each licensee is addressed as &ldquo;you&rdquo;. &ldquo;Licensees&rdquo; and\n&ldquo;recipients&rdquo; may be individuals or organizations.\n\nTo &ldquo;modify&rdquo; a work means to copy from or adapt all or part of the work in\na fashion requiring copyright permission, other than the making of an exact copy. The\nresulting work is called a &ldquo;modified version&rdquo; of the earlier work or a\nwork &ldquo;based on&rdquo; the earlier work.\n\nA &ldquo;covered work&rdquo; means either the unmodified Program or a work based on\nthe Program.\n\nTo &ldquo;propagate&rdquo; a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for infringement under\napplicable copyright law, except executing it on a computer or modifying a private\ncopy. Propagation includes copying, distribution (with or without modification),\nmaking available to the public, and in some countries other activities as well.\n\nTo &ldquo;convey&rdquo; a work means any kind of propagation that enables other\nparties to make or receive copies. Mere interaction with a user through a computer\nnetwork, with no transfer of a copy, is not conveying.\n\nAn interactive user interface displays &ldquo;Appropriate Legal Notices&rdquo; to the\nextent that it includes a convenient and prominently visible feature that (1)\ndisplays an appropriate copyright notice, and (2) tells the user that there is no\nwarranty for the work (except to the extent that warranties are provided), that\nlicensees may convey the work under this License, and how to view a copy of this\nLicense. If the interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n### 1. Source Code.\n\nThe &ldquo;source code&rdquo; for a work means the preferred form of the work for\nmaking modifications to it. &ldquo;Object code&rdquo; means any non-source form of a\nwork.\n\nA &ldquo;Standard Interface&rdquo; means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of interfaces\nspecified for a particular programming language, one that is widely used among\ndevelopers working in that language.\n\nThe &ldquo;System Libraries&rdquo; of an executable work include anything, other than\nthe work as a whole, that (a) is included in the normal form of packaging a Major\nComponent, but which is not part of that Major Component, and (b) serves only to\nenable use of the work with that Major Component, or to implement a Standard\nInterface for which an implementation is available to the public in source code form.\nA &ldquo;Major Component&rdquo;, in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system (if any) on which\nthe executable work runs, or a compiler used to produce the work, or an object code\ninterpreter used to run it.\n\nThe &ldquo;Corresponding Source&rdquo; for a work in object code form means all the\nsource code needed to generate, install, and (for an executable work) run the object\ncode and to modify the work, including scripts to control those activities. However,\nit does not include the work's System Libraries, or general-purpose tools or\ngenerally available free programs which are used unmodified in performing those\nactivities but which are not part of the work. For example, Corresponding Source\nincludes interface definition files associated with source files for the work, and\nthe source code for shared libraries and dynamically linked subprograms that the work\nis specifically designed to require, such as by intimate data communication or\ncontrol flow between those subprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users can regenerate\nautomatically from other parts of the Corresponding Source.\n\nThe Corresponding Source for a work in source code form is that same work.\n\n### 2. Basic Permissions.\n\nAll rights granted under this License are granted for the term of copyright on the\nProgram, and are irrevocable provided the stated conditions are met. This License\nexplicitly affirms your unlimited permission to run the unmodified Program. The\noutput from running a covered work is covered by this License only if the output,\ngiven its content, constitutes a covered work. This License acknowledges your rights\nof fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not convey, without\nconditions so long as your license otherwise remains in force. You may convey covered\nworks to others for the sole purpose of having them make modifications exclusively\nfor you, or provide you with facilities for running those works, provided that you\ncomply with the terms of this License in conveying all material for which you do not\ncontrol copyright. Those thus making or running the covered works for you must do so\nexclusively on your behalf, under your direction and control, on terms that prohibit\nthem from making any copies of your copyrighted material outside their relationship\nwith you.\n\nConveying under any other circumstances is permitted solely under the conditions\nstated below. Sublicensing is not allowed; section 10 makes it unnecessary.\n\n### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\nNo covered work shall be deemed part of an effective technological measure under any\napplicable law fulfilling obligations under article 11 of the WIPO copyright treaty\nadopted on 20 December 1996, or similar laws prohibiting or restricting circumvention\nof such measures.\n\nWhen you convey a covered work, you waive any legal power to forbid circumvention of\ntechnological measures to the extent such circumvention is effected by exercising\nrights under this License with respect to the covered work, and you disclaim any\nintention to limit operation or modification of the work as a means of enforcing,\nagainst the work's users, your or third parties' legal rights to forbid circumvention\nof technological measures.\n\n### 4. Conveying Verbatim Copies.\n\nYou may convey verbatim copies of the Program's source code as you receive it, in any\nmedium, provided that you conspicuously and appropriately publish on each copy an\nappropriate copyright notice; keep intact all notices stating that this License and\nany non-permissive terms added in accord with section 7 apply to the code; keep\nintact all notices of the absence of any warranty; and give all recipients a copy of\nthis License along with the Program.\n\nYou may charge any price or no price for each copy that you convey, and you may offer\nsupport or warranty protection for a fee.\n\n### 5. Conveying Modified Source Versions.\n\nYou may convey a work based on the Program, or the modifications to produce it from\nthe Program, in the form of source code under the terms of section 4, provided that\nyou also meet all of these conditions:\n\n* **a)** The work must carry prominent notices stating that you modified it, and giving a\nrelevant date.\n* **b)** The work must carry prominent notices stating that it is released under this\nLicense and any conditions added under section 7. This requirement modifies the\nrequirement in section 4 to &ldquo;keep intact all notices&rdquo;.\n* **c)** You must license the entire work, as a whole, under this License to anyone who\ncomes into possession of a copy. This License will therefore apply, along with any\napplicable section 7 additional terms, to the whole of the work, and all its parts,\nregardless of how they are packaged. This License gives no permission to license the\nwork in any other way, but it does not invalidate such permission if you have\nseparately received it.\n* **d)** If the work has interactive user interfaces, each must display Appropriate Legal\nNotices; however, if the Program has interactive interfaces that do not display\nAppropriate Legal Notices, your work need not make them do so.\n\nA compilation of a covered work with other separate and independent works, which are\nnot by their nature extensions of the covered work, and which are not combined with\nit such as to form a larger program, in or on a volume of a storage or distribution\nmedium, is called an &ldquo;aggregate&rdquo; if the compilation and its resulting\ncopyright are not used to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit. Inclusion of a covered work in an aggregate\ndoes not cause this License to apply to the other parts of the aggregate.\n\n### 6. Conveying Non-Source Forms.\n\nYou may convey a covered work in object code form under the terms of sections 4 and\n5, provided that you also convey the machine-readable Corresponding Source under the\nterms of this License, in one of these ways:\n\n* **a)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by the Corresponding Source fixed on a\ndurable physical medium customarily used for software interchange.\n* **b)** Convey the object code in, or embodied in, a physical product (including a\nphysical distribution medium), accompanied by a written offer, valid for at least\nthree years and valid for as long as you offer spare parts or customer support for\nthat product model, to give anyone who possesses the object code either (1) a copy of\nthe Corresponding Source for all the software in the product that is covered by this\nLicense, on a durable physical medium customarily used for software interchange, for\na price no more than your reasonable cost of physically performing this conveying of\nsource, or (2) access to copy the Corresponding Source from a network server at no\ncharge.\n* **c)** Convey individual copies of the object code with a copy of the written offer to\nprovide the Corresponding Source. This alternative is allowed only occasionally and\nnoncommercially, and only if you received the object code with such an offer, in\naccord with subsection 6b.\n* **d)** Convey the object code by offering access from a designated place (gratis or for\na charge), and offer equivalent access to the Corresponding Source in the same way\nthrough the same place at no further charge. You need not require recipients to copy\nthe Corresponding Source along with the object code. If the place to copy the object\ncode is a network server, the Corresponding Source may be on a different server\n(operated by you or a third party) that supports equivalent copying facilities,\nprovided you maintain clear directions next to the object code saying where to find\nthe Corresponding Source. Regardless of what server hosts the Corresponding Source,\nyou remain obligated to ensure that it is available for as long as needed to satisfy\nthese requirements.\n* **e)** Convey the object code using peer-to-peer transmission, provided you inform\nother peers where the object code and Corresponding Source of the work are being\noffered to the general public at no charge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded from the\nCorresponding Source as a System Library, need not be included in conveying the\nobject code work.\n\nA &ldquo;User Product&rdquo; is either (1) a &ldquo;consumer product&rdquo;, which\nmeans any tangible personal property which is normally used for personal, family, or\nhousehold purposes, or (2) anything designed or sold for incorporation into a\ndwelling. In determining whether a product is a consumer product, doubtful cases\nshall be resolved in favor of coverage. For a particular product received by a\nparticular user, &ldquo;normally used&rdquo; refers to a typical or common use of\nthat class of product, regardless of the status of the particular user or of the way\nin which the particular user actually uses, or expects or is expected to use, the\nproduct. A product is a consumer product regardless of whether the product has\nsubstantial commercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n&ldquo;Installation Information&rdquo; for a User Product means any methods,\nprocedures, authorization keys, or other information required to install and execute\nmodified versions of a covered work in that User Product from a modified version of\nits Corresponding Source. The information must suffice to ensure that the continued\nfunctioning of the modified object code is in no case prevented or interfered with\nsolely because modification has been made.\n\nIf you convey an object code work under this section in, or with, or specifically for\nuse in, a User Product, and the conveying occurs as part of a transaction in which\nthe right of possession and use of the User Product is transferred to the recipient\nin perpetuity or for a fixed term (regardless of how the transaction is\ncharacterized), the Corresponding Source conveyed under this section must be\naccompanied by the Installation Information. But this requirement does not apply if\nneither you nor any third party retains the ability to install modified object code\non the User Product (for example, the work has been installed in ROM).\n\nThe requirement to provide Installation Information does not include a requirement to\ncontinue to provide support service, warranty, or updates for a work that has been\nmodified or installed by the recipient, or for the User Product in which it has been\nmodified or installed. Access to a network may be denied when the modification itself\nmaterially and adversely affects the operation of the network or violates the rules\nand protocols for communication across the network.\n\nCorresponding Source conveyed, and Installation Information provided, in accord with\nthis section must be in a format that is publicly documented (and with an\nimplementation available to the public in source code form), and must require no\nspecial password or key for unpacking, reading or copying.\n\n### 7. Additional Terms.\n\n&ldquo;Additional permissions&rdquo; are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions. Additional\npermissions that are applicable to the entire Program shall be treated as though they\nwere included in this License, to the extent that they are valid under applicable\nlaw. If additional permissions apply only to part of the Program, that part may be\nused separately under those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option remove any\nadditional permissions from that copy, or from any part of it. (Additional\npermissions may be written to require their own removal in certain cases when you\nmodify the work.) You may place additional permissions on material, added by you to a\ncovered work, for which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you add to a\ncovered work, you may (if authorized by the copyright holders of that material)\nsupplement the terms of this License with terms:\n\n* **a)** Disclaiming warranty or limiting liability differently from the terms of\nsections 15 and 16 of this License; or\n* **b)** Requiring preservation of specified reasonable legal notices or author\nattributions in that material or in the Appropriate Legal Notices displayed by works\ncontaining it; or\n* **c)** Prohibiting misrepresentation of the origin of that material, or requiring that\nmodified versions of such material be marked in reasonable ways as different from the\noriginal version; or\n* **d)** Limiting the use for publicity purposes of names of licensors or authors of the\nmaterial; or\n* **e)** Declining to grant rights under trademark law for use of some trade names,\ntrademarks, or service marks; or\n* **f)** Requiring indemnification of licensors and authors of that material by anyone\nwho conveys the material (or modified versions of it) with contractual assumptions of\nliability to the recipient, for any liability that these contractual assumptions\ndirectly impose on those licensors and authors.\n\nAll other non-permissive additional terms are considered &ldquo;further\nrestrictions&rdquo; within the meaning of section 10. If the Program as you received\nit, or any part of it, contains a notice stating that it is governed by this License\nalong with a term that is a further restriction, you may remove that term. If a\nlicense document contains a further restriction but permits relicensing or conveying\nunder this License, you may add to a covered work material governed by the terms of\nthat license document, provided that the further restriction does not survive such\nrelicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you must place, in\nthe relevant source files, a statement of the additional terms that apply to those\nfiles, or a notice indicating where to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the form of a\nseparately written license, or stated as exceptions; the above requirements apply\neither way.\n\n### 8. Termination.\n\nYou may not propagate or modify a covered work except as expressly provided under\nthis License. Any attempt otherwise to propagate or modify it is void, and will\nautomatically terminate your rights under this License (including any patent licenses\ngranted under the third paragraph of section 11).\n\nHowever, if you cease all violation of this License, then your license from a\nparticular copyright holder is reinstated (a) provisionally, unless and until the\ncopyright holder explicitly and finally terminates your license, and (b) permanently,\nif the copyright holder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is reinstated permanently\nif the copyright holder notifies you of the violation by some reasonable means, this\nis the first time you have received notice of violation of this License (for any\nwork) from that copyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the licenses of\nparties who have received copies or rights from you under this License. If your\nrights have been terminated and not permanently reinstated, you do not qualify to\nreceive new licenses for the same material under section 10.\n\n### 9. Acceptance Not Required for Having Copies.\n\nYou are not required to accept this License in order to receive or run a copy of the\nProgram. Ancillary propagation of a covered work occurring solely as a consequence of\nusing peer-to-peer transmission to receive a copy likewise does not require\nacceptance. However, nothing other than this License grants you permission to\npropagate or modify any covered work. These actions infringe copyright if you do not\naccept this License. Therefore, by modifying or propagating a covered work, you\nindicate your acceptance of this License to do so.\n\n### 10. Automatic Licensing of Downstream Recipients.\n\nEach time you convey a covered work, the recipient automatically receives a license\nfrom the original licensors, to run, modify and propagate that work, subject to this\nLicense. You are not responsible for enforcing compliance by third parties with this\nLicense.\n\nAn &ldquo;entity transaction&rdquo; is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an organization, or\nmerging organizations. If propagation of a covered work results from an entity\ntransaction, each party to that transaction who receives a copy of the work also\nreceives whatever licenses to the work the party's predecessor in interest had or\ncould give under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if the predecessor\nhas it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the rights granted or\naffirmed under this License. For example, you may not impose a license fee, royalty,\nor other charge for exercise of rights granted under this License, and you may not\ninitiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging\nthat any patent claim is infringed by making, using, selling, offering for sale, or\nimporting the Program or any portion of it.\n\n### 11. Patents.\n\nA &ldquo;contributor&rdquo; is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based. The work thus\nlicensed is called the contributor's &ldquo;contributor version&rdquo;.\n\nA contributor's &ldquo;essential patent claims&rdquo; are all patent claims owned or\ncontrolled by the contributor, whether already acquired or hereafter acquired, that\nwould be infringed by some manner, permitted by this License, of making, using, or\nselling its contributor version, but do not include claims that would be infringed\nonly as a consequence of further modification of the contributor version. For\npurposes of this definition, &ldquo;control&rdquo; includes the right to grant patent\nsublicenses in a manner consistent with the requirements of this License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free patent license\nunder the contributor's essential patent claims, to make, use, sell, offer for sale,\nimport and otherwise run, modify and propagate the contents of its contributor\nversion.\n\nIn the following three paragraphs, a &ldquo;patent license&rdquo; is any express\nagreement or commitment, however denominated, not to enforce a patent (such as an\nexpress permission to practice a patent or covenant not to sue for patent\ninfringement). To &ldquo;grant&rdquo; such a patent license to a party means to make\nsuch an agreement or commitment not to enforce a patent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license, and the\nCorresponding Source of the work is not available for anyone to copy, free of charge\nand under the terms of this License, through a publicly available network server or\nother readily accessible means, then you must either (1) cause the Corresponding\nSource to be so available, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner consistent with\nthe requirements of this License, to extend the patent license to downstream\nrecipients. &ldquo;Knowingly relying&rdquo; means you have actual knowledge that, but\nfor the patent license, your conveying the covered work in a country, or your\nrecipient's use of the covered work in a country, would infringe one or more\nidentifiable patents in that country that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or arrangement, you\nconvey, or propagate by procuring conveyance of, a covered work, and grant a patent\nlicense to some of the parties receiving the covered work authorizing them to use,\npropagate, modify or convey a specific copy of the covered work, then the patent\nlicense you grant is automatically extended to all recipients of the covered work and\nworks based on it.\n\nA patent license is &ldquo;discriminatory&rdquo; if it does not include within the\nscope of its coverage, prohibits the exercise of, or is conditioned on the\nnon-exercise of one or more of the rights that are specifically granted under this\nLicense. You may not convey a covered work if you are a party to an arrangement with\na third party that is in the business of distributing software, under which you make\npayment to the third party based on the extent of your activity of conveying the\nwork, and under which the third party grants, to any of the parties who would receive\nthe covered work from you, a discriminatory patent license (a) in connection with\ncopies of the covered work conveyed by you (or copies made from those copies), or (b)\nprimarily for and in connection with specific products or compilations that contain\nthe covered work, unless you entered into that arrangement, or that patent license\nwas granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting any implied\nlicense or other defenses to infringement that may otherwise be available to you\nunder applicable patent law.\n\n### 12. No Surrender of Others' Freedom.\n\nIf conditions are imposed on you (whether by court order, agreement or otherwise)\nthat contradict the conditions of this License, they do not excuse you from the\nconditions of this License. If you cannot convey a covered work so as to satisfy\nsimultaneously your obligations under this License and any other pertinent\nobligations, then as a consequence you may not convey it at all. For example, if you\nagree to terms that obligate you to collect a royalty for further conveying from\nthose to whom you convey the Program, the only way you could satisfy both those terms\nand this License would be to refrain entirely from conveying the Program.\n\n### 13. Use with the GNU Affero General Public License.\n\nNotwithstanding any other provision of this License, you have permission to link or\ncombine any covered work with a work licensed under version 3 of the GNU Affero\nGeneral Public License into a single combined work, and to convey the resulting work.\nThe terms of this License will continue to apply to the part which is the covered\nwork, but the special requirements of the GNU Affero General Public License, section\n13, concerning interaction through a network will apply to the combination as such.\n\n### 14. Revised Versions of this License.\n\nThe Free Software Foundation may publish revised and/or new versions of the GNU\nGeneral Public License from time to time. Such new versions will be similar in spirit\nto the present version, but may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number. If the Program specifies that\na certain numbered version of the GNU General Public License &ldquo;or any later\nversion&rdquo; applies to it, you have the option of following the terms and\nconditions either of that numbered version or of any later version published by the\nFree Software Foundation. If the Program does not specify a version number of the GNU\nGeneral Public License, you may choose any version ever published by the Free\nSoftware Foundation.\n\nIf the Program specifies that a proxy can decide which future versions of the GNU\nGeneral Public License can be used, that proxy's public statement of acceptance of a\nversion permanently authorizes you to choose that version for the Program.\n\nLater license versions may give you additional or different permissions. However, no\nadditional obligations are imposed on any author or copyright holder as a result of\nyour choosing to follow a later version.\n\n### 15. Disclaimer of Warranty.\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM &ldquo;AS IS&rdquo; WITHOUT WARRANTY OF ANY KIND, EITHER\nEXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE\nQUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE\nDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n### 16. Limitation of Liability.\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY\nCOPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS\nPERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,\nINCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nPROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE\nOR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE\nWITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n### 17. Interpretation of Sections 15 and 16.\n\nIf the disclaimer of warranty and limitation of liability provided above cannot be\ngiven local legal effect according to their terms, reviewing courts shall apply local\nlaw that most closely approximates an absolute waiver of all civil liability in\nconnection with the Program, unless a warranty or assumption of liability accompanies\na copy of the Program in return for a fee.\n\nEND OF TERMS AND CONDITIONS\n\n## How to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest possible use to\nthe public, the best way to achieve this is to make it free software which everyone\ncan redistribute and change under these terms.\n\nTo do so, attach the following notices to the program. It is safest to attach them\nto the start of each source file to most effectively state the exclusion of warranty;\nand each file should have at least the &ldquo;copyright&rdquo; line and a pointer to\nwhere the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program does terminal interaction, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type 'show c' for details.\n\nThe hypothetical commands 'show w' and 'show c' should show the appropriate parts of\nthe General Public License. Of course, your program's commands might be different;\nfor a GUI interface, you would use an &ldquo;about box&rdquo;.\n\nYou should also get your employer (if you work as a programmer) or school, if any, to\nsign a &ldquo;copyright disclaimer&rdquo; for the program, if necessary. For more\ninformation on this, and how to apply and follow the GNU GPL, see\n&lt;<https://www.gnu.org/licenses/>&gt;.\n\nThe GNU General Public License does not permit incorporating your program into\nproprietary programs. If your program is a subroutine library, you may consider it\nmore useful to permit linking proprietary applications with the library. If this is\nwhat you want to do, use the GNU Lesser General Public License instead of this\nLicense. But first, please read\n&lt;<https://www.gnu.org/philosophy/why-not-lgpl.html>&gt;.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "exclude *.pyc .DS_Store .gitignore MANIFEST.in\ninclude setup.py\ninclude distribute_setup.py\ninclude README.md\ninclude LICENSE\nrecursive-include bin *\nrecursive-include pwnagotchi *.py\nrecursive-include pwnagotchi *.yml\nrecursive-include pwnagotchi *.*\n"
  },
  {
    "path": "Makefile",
    "content": "PACKER_VERSION=1.7.2\nPWN_HOSTNAME=pwnagotchi\nPWN_VERSION=master\n\nall: clean install image\n\nlangs:\n\t@for lang in pwnagotchi/locale/*/; do\\\n\t\techo \"compiling language: $$lang ...\"; \\\n\t\t./scripts/language.sh compile $$(basename $$lang); \\\n    done\n\ninstall:\n\tcurl https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_amd64.zip -o /tmp/packer.zip\n\tunzip /tmp/packer.zip -d /tmp\n\tsudo mv /tmp/packer /usr/bin/packer\n\tgit clone https://github.com/solo-io/packer-builder-arm-image /tmp/packer-builder-arm-image\n\tcd /tmp/packer-builder-arm-image && go get -d ./... && go build\n\tsudo cp /tmp/packer-builder-arm-image/packer-builder-arm-image /usr/bin\n\nimage:\n\tcd builder && sudo /usr/bin/packer build -var \"pwn_hostname=$(PWN_HOSTNAME)\" -var \"pwn_version=$(PWN_VERSION)\" pwnagotchi.json\n\tsudo mv builder/output-pwnagotchi/image pwnagotchi-raspbian-lite-$(PWN_VERSION).img\n\tsudo sha256sum pwnagotchi-raspbian-lite-$(PWN_VERSION).img > pwnagotchi-raspbian-lite-$(PWN_VERSION).sha256\n\tsudo zip pwnagotchi-raspbian-lite-$(PWN_VERSION).zip pwnagotchi-raspbian-lite-$(PWN_VERSION).sha256 pwnagotchi-raspbian-lite-$(PWN_VERSION).img\n\nclean:\n\trm -rf /tmp/packer-builder-arm-image\n\trm -f pwnagotchi-raspbian-lite-*.zip pwnagotchi-raspbian-lite-*.img pwnagotchi-raspbian-lite-*.sha256\n\trm -rf builder/output-pwnagotchi  builder/packer_cache\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <small>Join the project community on our server!</small>\n  <br/><br/>\n  <a href=\"https://discord.gg/https://discord.gg/btZpkp45gQ\" target=\"_blank\" title=\"Join our community!\">\n    <img src=\"https://dcbadge.limes.pink/api/server/https://discord.gg/btZpkp45gQ\"/>\n  </a>\n</p>\n<hr/>\n\n<p align=\"center\">\n    <a href=\"https://github.com/evilsocket/pwnagotchi/releases/latest\"><img alt=\"Release\" src=\"https://img.shields.io/github/release/evilsocket/pwnagotchi.svg?style=flat-square\"></a>\n    <a href=\"https://github.com/evilsocket/pwnagotchi/blob/master/LICENSE.md\"><img alt=\"Software License\" src=\"https://img.shields.io/badge/license-GPL3-brightgreen.svg?style=flat-square\"></a>\n    <a href=\"https://github.com/evilsocket/pwnagotchi/graphs/contributors\"><img alt=\"Contributors\" src=\"https://img.shields.io/github/contributors/evilsocket/pwnagotchi\"/></a>\n    <a href=\"https://twitter.com/intent/follow?screen_name=pwnagotchi\"><img src=\"https://img.shields.io/twitter/follow/pwnagotchi?style=social&logo=twitter\" alt=\"follow on Twitter\"></a>\n    <br/>\n    <br/>\n    <img src=\"https://www.evilsocket.net/images/human-coded.png\" height=\"30px\" alt=\"This project is 100% made by humans.\"/>\n\n</p>\n\n[Pwnagotchi](https://pwnagotchi.ai/) is an [A2C](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752)-based \"AI\" leveraging [bettercap](https://www.bettercap.org/) that learns from its surrounding WiFi environment to maximize the crackable WPA key material it captures (either passively, or by performing authentication and association attacks). This material is collected as PCAP files containing any form of handshake supported by [hashcat](https://hashcat.net/hashcat/), including [PMKIDs](https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/), \nfull and half WPA handshakes.\n\n![ui](https://i.imgur.com/X68GXrn.png)\n\nInstead of merely playing [Super Mario or Atari games](https://becominghuman.ai/getting-mario-back-into-the-gym-setting-up-super-mario-bros-in-openais-gym-8e39a96c1e41?gi=c4b66c3d5ced) like most reinforcement learning-based \"AI\" *(yawn)*, Pwnagotchi tunes [its parameters](https://github.com/evilsocket/pwnagotchi/blob/master/pwnagotchi/defaults.toml) over time to **get better at pwning WiFi things to** in the environments you expose it to. \n\nMore specifically, Pwnagotchi is using an [LSTM with MLP feature extractor](https://stable-baselines.readthedocs.io/en/master/modules/policies.html#stable_baselines.common.policies.MlpLstmPolicy) as its policy network for the [A2C agent](https://stable-baselines.readthedocs.io/en/master/modules/a2c.html). If you're unfamiliar with A2C, here is [a very good introductory explanation](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752) (in comic form!) of the basic principles behind how Pwnagotchi learns. (You can read more about how Pwnagotchi learns in the [Usage](https://www.pwnagotchi.ai/usage/#training-the-ai) doc.)\n\n**Keep in mind:** Unlike the usual RL simulations, Pwnagotchi learns over time. Time for a Pwnagotchi is measured in epochs; a single epoch can last from a few seconds to minutes, depending on how many access points and client stations are visible. Do not expect your Pwnagotchi to perform amazingly well at the very beginning, as it will be [exploring](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752) several combinations of [key parameters](https://www.pwnagotchi.ai/usage/#training-the-ai) to determine ideal adjustments for pwning the particular environment you are exposing it to during its beginning epochs ... but ** listen to your Pwnagotchi when it tells you it's boring!** Bring it into novel WiFi environments with you and have it observe new networks and capture new handshakes—and you'll see. :)\n\nMultiple units within close physical proximity can \"talk\" to each other, advertising their presence to each other by broadcasting custom information elements using a parasite protocol I've built on top of the existing dot11 standard. Over time, two or more units trained together will learn to cooperate upon detecting each other's presence by dividing the available channels among them for optimal pwnage.\n\n## Documentation\n\nhttps://www.pwnagotchi.ai\n\n## Links\n\n&nbsp; | Official Links\n---------|-------\nWebsite | [pwnagotchi.ai](https://pwnagotchi.ai/)\nForum | [community.pwnagotchi.ai](https://community.pwnagotchi.ai/)\nSlack | [pwnagotchi.slack.com](https://invite.pwnagotchi.ai/)\nSubreddit | [r/pwnagotchi](https://www.reddit.com/r/pwnagotchi/)\nTwitter | [@pwnagotchi](https://twitter.com/pwnagotchi)\n\n## License\n\n`pwnagotchi` is made with ♥  by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It is released under the GPL3 license.\n"
  },
  {
    "path": "bin/pwnagotchi",
    "content": "#!/usr/bin/python3\nimport logging\nimport argparse\nimport time\nimport signal\nimport sys\nimport toml\n\nimport pwnagotchi\nfrom pwnagotchi import utils\nfrom pwnagotchi.plugins import cmd as plugins_cmd\nfrom pwnagotchi import log\nfrom pwnagotchi import restart\nfrom pwnagotchi import fs\nfrom pwnagotchi.utils import DottedTomlEncoder\n\n\ndef do_clear(display):\n    logging.info(\"clearing the display ...\")\n    display.clear()\n    sys.exit(0)\n\n\ndef do_manual_mode(agent):\n    logging.info(\"entering manual mode ...\")\n\n    agent.mode = 'manual'\n    agent.last_session.parse(agent.view(), args.skip_session)\n    if not args.skip_session:\n        logging.info(\n            \"the last session lasted %s (%d completed epochs, trained for %d), average reward:%s (min:%s max:%s)\" % (\n                agent.last_session.duration_human,\n                agent.last_session.epochs,\n                agent.last_session.train_epochs,\n                agent.last_session.avg_reward,\n                agent.last_session.min_reward,\n                agent.last_session.max_reward))\n\n    while True:\n        display.on_manual_mode(agent.last_session)\n        time.sleep(5)\n        if grid.is_connected():\n            plugins.on('internet_available', agent)\n\n\ndef do_auto_mode(agent):\n    logging.info(\"entering auto mode ...\")\n\n    agent.mode = 'auto'\n    agent.start()\n\n    while True:\n        try:\n            # recon on all channels\n            agent.recon()\n            # get nearby access points grouped by channel\n            channels = agent.get_access_points_by_channel()\n            # for each channel\n            for ch, aps in channels:\n                agent.set_channel(ch)\n\n                if not agent.is_stale() and agent.any_activity():\n                    logging.info(\"%d access points on channel %d\" % (len(aps), ch))\n\n                # for each ap on this channel\n                for ap in aps:\n                    # send an association frame in order to get for a PMKID\n                    agent.associate(ap)\n                    # deauth all client stations in order to get a full handshake\n                    for sta in ap['clients']:\n                        agent.deauth(ap, sta)\n\n            # An interesting effect of this:\n            #\n            # From Pwnagotchi's perspective, the more new access points\n            # and / or client stations nearby, the longer one epoch of\n            # its relative time will take ... basically, in Pwnagotchi's universe,\n            # WiFi electromagnetic fields affect time like gravitational fields\n            # affect ours ... neat ^_^\n            agent.next_epoch()\n\n            if grid.is_connected():\n                plugins.on('internet_available', agent)\n\n        except Exception as e:\n            if str(e).find(\"wifi.interface not set\") > 0:\n                logging.exception(\"main loop exception due to unavailable wifi device, likely programmatically disabled (%s)\", e)\n                logging.info(\"sleeping 60 seconds then advancing to next epoch to allow for cleanup code to trigger\")\n                time.sleep(60)\n                agent.next_epoch()\n            else:\n                logging.exception(\"main loop exception (%s)\", e)\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser()\n    parser = plugins_cmd.add_parsers(parser)\n\n    parser.add_argument('-C', '--config', action='store', dest='config', default='/etc/pwnagotchi/default.toml',\n                        help='Main configuration file.')\n    parser.add_argument('-U', '--user-config', action='store', dest='user_config', default='/etc/pwnagotchi/config.toml',\n                        help='If this file exists, configuration will be merged and this will override default values.')\n\n    parser.add_argument('--manual', dest=\"do_manual\", action=\"store_true\", default=False, help=\"Manual mode.\")\n    parser.add_argument('--skip-session', dest=\"skip_session\", action=\"store_true\", default=False,\n                        help=\"Skip last session parsing in manual mode.\")\n\n    parser.add_argument('--clear', dest=\"do_clear\", action=\"store_true\", default=False,\n                        help=\"Clear the ePaper display and exit.\")\n\n    parser.add_argument('--debug', dest=\"debug\", action=\"store_true\", default=False,\n                        help=\"Enable debug logs.\")\n\n    parser.add_argument('--version', dest=\"version\", action=\"store_true\", default=False,\n                        help=\"Print the version.\")\n\n    parser.add_argument('--print-config', dest=\"print_config\", action=\"store_true\", default=False,\n                        help=\"Print the configuration.\")\n\n    args = parser.parse_args()\n\n\n    if plugins_cmd.used_plugin_cmd(args):\n      config = utils.load_config(args)\n      log.setup_logging(args, config)\n      rc = plugins_cmd.handle_cmd(args, config)\n      sys.exit(rc)\n\n    if args.version:\n        print(pwnagotchi.__version__)\n        sys.exit(0)\n\n    config = utils.load_config(args)\n\n    if args.print_config:\n        print(toml.dumps(config, encoder=DottedTomlEncoder()))\n        sys.exit(0)\n\n    from pwnagotchi.identity import KeyPair\n    from pwnagotchi.agent import Agent\n    from pwnagotchi.ui import fonts\n    from pwnagotchi.ui.display import Display\n    from pwnagotchi import grid\n    from pwnagotchi import plugins\n\n    pwnagotchi.config = config\n    fs.setup_mounts(config)\n    log.setup_logging(args, config)\n    fonts.init(config)\n\n    pwnagotchi.set_name(config['main']['name'])\n\n    plugins.load(config)\n\n    display = Display(config=config, state={'name': '%s>' % pwnagotchi.name()})\n\n    if args.do_clear:\n        do_clear(display)\n        sys.exit(0)\n\n    agent = Agent(view=display, config=config, keypair=KeyPair(view=display))\n\n    def usr1_handler(*unused):\n        logging.info('Received USR1 singal. Restart process ...')\n        restart(\"MANU\" if args.do_manual else \"AUTO\")\n\n    signal.signal(signal.SIGUSR1, usr1_handler)\n\n    if args.do_manual:\n        do_manual_mode(agent)\n    else:\n        do_auto_mode(agent)\n"
  },
  {
    "path": "builder/data/etc/bash_completion.d/pwnagotchi_completion.sh",
    "content": "_show_complete()\n{\n    local cur opts node_names all_options opt_line\n    all_options=\"\npwnagotchi -h --help -C --config -U --user-config --manual --skip-session --clear --debug --version --print-config {plugins}\npwnagotchi plugins -h --help {list,install,enable,disable,uninstall,update,upgrade}\npwnagotchi plugins list -i --installed -h --help\npwnagotchi plugins install -h --help\npwnagotchi plugins uninstall -h --help\npwnagotchi plugins enable -h --help\npwnagotchi plugins disable -h --help\npwnagotchi plugins update -h --help\npwnagotchi plugins upgrade -h --help\n\"\n    COMPREPLY=()\n    cur=\"${COMP_WORDS[COMP_CWORD]}\"\n    cmd=\"${COMP_WORDS[@]:0:${#COMP_WORDS[@]}-1}\"\n    opt_line=\"$(grep -m1 \"$cmd\" <<<$all_options)\"\n    if [[ ${cur} == -* ]] ; then\n        opts=\"$(echo $opt_line | tr ' ' '\\n' | awk '/^ *-/{gsub(\"[^a-zA-Z0-9-]\",\"\",$1);print $1}')\"\n        COMPREPLY=( $(compgen -W \"${opts}\" -- ${cur}) )\n        return 0\n    fi\n\n    opts=\"$(echo $opt_line | grep -Po '{\\K[^}]+' | tr ',' '\\n')\"\n    COMPREPLY=( $(compgen -W \"${opts}\" -- ${cur}) )\n}\n\ncomplete -F _show_complete pwnagotchi\n"
  },
  {
    "path": "builder/data/etc/network/interfaces.d/eth0-cfg",
    "content": "allow-hotplug eth0\niface eth0 inet dhcp"
  },
  {
    "path": "builder/data/etc/network/interfaces.d/lo-cfg",
    "content": "auto lo\niface lo inet loopback"
  },
  {
    "path": "builder/data/etc/network/interfaces.d/usb0-cfg",
    "content": "allow-hotplug usb0\niface usb0 inet static\n  address 10.0.0.2\n  netmask 255.255.255.0\n  network 10.0.0.0\n  broadcast 10.0.0.255\n  gateway 10.0.0.1\n  metric 20\n"
  },
  {
    "path": "builder/data/etc/network/interfaces.d/wlan0-cfg",
    "content": "allow-hotplug wlan0\niface wlan0 inet static"
  },
  {
    "path": "builder/data/etc/systemd/system/bettercap.service",
    "content": "[Unit]\nDescription=bettercap api.rest service.\nDocumentation=https://bettercap.org\nWants=network.target\n\n[Service]\nType=simple\nPermissionsStartOnly=true\nExecStart=/usr/bin/bettercap-launcher\nRestart=always\nRestartSec=30\n\n[Install]\nWantedBy=multi-user.target"
  },
  {
    "path": "builder/data/etc/systemd/system/pwnagotchi.service",
    "content": "[Unit]\nDescription=pwnagotchi Deep Reinforcement Learning instrumenting bettercap for WiFI pwning.\nDocumentation=https://pwnagotchi.ai\nWants=network.target\nAfter=pwngrid-peer.service\n\n[Service]\nType=simple\nWorkingDirectory=/tmp\nPermissionsStartOnly=true\nExecStart=/usr/bin/pwnagotchi-launcher\nRestart=always\nRestartSec=30\nTasksMax=infinity\nLimitNPROC=infinity\nStandardOutput=null\nStandardError=null\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "builder/data/etc/systemd/system/pwngrid-peer.service",
    "content": "[Unit]\nDescription=pwngrid peer service.\nDocumentation=https://pwnagotchi.ai\nWants=network.target\nAfter=bettercap.service\n\n[Service]\nType=simple\nPermissionsStartOnly=true\nExecStart=/usr/bin/pwngrid -keys /etc/pwnagotchi -address 127.0.0.1:8666 -client-token /root/.api-enrollment.json -wait -log /var/log/pwngrid-peer.log -iface mon0\nRestart=always\nRestartSec=30\n\n[Install]\nWantedBy=multi-user.target"
  },
  {
    "path": "builder/data/usr/bin/bettercap-launcher",
    "content": "#!/usr/bin/env bash\nsource /usr/bin/pwnlib\n\n# we need to decrypt something\nif is_crypted_mode; then\n  while ! is_decrypted; do\n    echo \"Waiting for decryption...\"\n    sleep 1\n  done\nfi\n\n# check if wifi driver is bugged\nif ! check_brcm; then\n  if ! reload_brcm; then\n    echo \"Could not reload wifi driver. Reboot\"\n    reboot\n  fi\n  sleep 10\nfi\n\n# start mon0\nstart_monitor_interface\n\nif is_auto_mode_no_delete; then\n  /usr/bin/bettercap -no-colors -caplet pwnagotchi-auto -iface mon0\nelse\n  /usr/bin/bettercap -no-colors -caplet pwnagotchi-manual -iface mon0\nfi\n"
  },
  {
    "path": "builder/data/usr/bin/decryption-webserver",
    "content": "#!/usr/bin/env python3\n\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\nfrom urllib.parse import parse_qsl\n\n\n_HTML_FORM_TEMPLATE = \"\"\"\n<!DOCTYPE html>\n<html>\n<head>\n  <title>Decryption</title>\n  <style>\n    body {{ text-align: center; padding: 150px; }}\n    h1 {{ font-size: 50px; }}\n    body {{ font: 20px Helvetica, sans-serif; color: #333; }}\n    article {{ display: block; text-align: center; width: 650px; margin: 0 auto;}}\n    input {{\n      padding: 12px 20px;\n      margin: 8px 0;\n      box-sizing: border-box;\n      border: 1px solid #ccc;\n    }}\n    input[type=password] {{\n      width: 75%;\n      font-size: 24px;\n    }}\n    input[type=submit] {{\n      cursor: pointer;\n      width: 75%;\n    }}\n    input[type=submit]:hover {{\n      background-color: #d9d9d9;\n    }}\n  </style>\n</head>\n<body>\n  <article>\n      <h1>Decryption</h1>\n      <p>Some of your files are encrypted.</p>\n      <p>Please provide the decryption password.</p>\n      <div>\n        <form action=\"/set-password\" method=\"POST\">\n          {password_fields}\n          <input type=\"submit\" value=\"Submit\">\n        </form>\n      </div>\n  </article>\n</body>\n</html>\n\"\"\"\n\nPOST_RESPONSE = \"\"\"\n<!DOCTYPE html>\n<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<style>\n/* Center the loader */\n#loader {\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  z-index: 1;\n  width: 150px;\n  height: 150px;\n  margin: -75px 0 0 -75px;\n  border: 16px solid #f3f3f3;\n  border-radius: 50%;\n  border-top: 16px solid #3498db;\n  width: 120px;\n  height: 120px;\n  -webkit-animation: spin 2s linear infinite;\n  animation: spin 2s linear infinite;\n}\n\n@-webkit-keyframes spin {\n  0% { -webkit-transform: rotate(0deg); }\n  100% { -webkit-transform: rotate(360deg); }\n}\n\n@keyframes spin {\n  0% { transform: rotate(0deg); }\n  100% { transform: rotate(360deg); }\n}\n\n#myDiv {\n  display: none;\n  text-align: center;\n}\n</style>\n<script type=\"text/javascript\">\n\nfunction checkPwnagotchi() {\n    var target = 'http://' + document.location.hostname + ':8080/';\n    var xhr = new XMLHttpRequest();\n    xhr.open('GET', target);\n    xhr.onreadystatechange = function () {\n        if (xhr.readyState == 4) {\n            if (xhr.status == 200 || xhr.status == 401) {\n                window.location.replace(target);\n            }else{\n                setTimeout(checkPwnagotchi, 1000);\n            }\n        }\n    };\n    xhr.send();\n}\n\nsetTimeout(checkPwnagotchi, 1000);\n\n</script>\n</head>\n<body style=\"margin:0;\">\n\n<div id=\"loader\"></div>\n\n</body>\n</html>\n\"\"\"\n\nHTML_FORM = None\n\nclass SimpleHTTPRequestHandler(BaseHTTPRequestHandler):\n\n    def do_GET(self):\n        self.send_response(200)\n        self.end_headers()\n        self.wfile.write(HTML_FORM.encode())\n\n    def do_POST(self):\n        content_length = int(self.headers['Content-Length'])\n        body = self.rfile.read(content_length)\n        for mapping, password in parse_qsl(body.decode('UTF-8')):\n            with open('/tmp/.pwnagotchi-secret-{}'.format(mapping), 'wt') as pwfile:\n                pwfile.write(password)\n        self.send_response(200)\n        self.end_headers()\n        self.wfile.write(POST_RESPONSE.encode())\n\n\nwith open('/root/.pwnagotchi-crypted') as crypted_file:\n    mappings = [line.split()[0] for line in crypted_file.readlines()]\n    fields = ''.join(['<label for=\"{m}\">Passphrase for {m}:</label>\\n<input type=\"password\" id=\"{m}\" name=\"{m}\" value=\"\"><br>'.format(m=m)\n              for m in mappings])\n    HTML_FORM = _HTML_FORM_TEMPLATE.format(password_fields=fields)\n\nhttpd = HTTPServer(('0.0.0.0', 80), SimpleHTTPRequestHandler)\nhttpd.serve_forever()\n"
  },
  {
    "path": "builder/data/usr/bin/hdmioff",
    "content": "#!/usr/bin/env bash\nsudo /opt/vc/bin/tvservice -o"
  },
  {
    "path": "builder/data/usr/bin/hdmion",
    "content": "#!/usr/bin/env bash\nsudo /opt/vc/bin/tvservice -p"
  },
  {
    "path": "builder/data/usr/bin/monstart",
    "content": "#!/usr/bin/env bash\nsource /usr/bin/pwnlib\nstart_monitor_interface\n"
  },
  {
    "path": "builder/data/usr/bin/monstop",
    "content": "#!/usr/bin/env bash\nsource /usr/bin/pwnlib\nstop_monitor_interface"
  },
  {
    "path": "builder/data/usr/bin/pwnagotchi-launcher",
    "content": "#!/usr/bin/env bash\nsource /usr/bin/pwnlib\n\n# we need to decrypt something\nif is_crypted_mode; then\n  while ! is_decrypted; do\n    echo \"Waiting for decryption...\"\n    sleep 1\n  done\nfi\n\n# blink 10 times to signal ready state\nblink_led 10 &\n\nif is_auto_mode; then\n  /usr/local/bin/pwnagotchi\nelse\n  /usr/local/bin/pwnagotchi --manual\nfi\n"
  },
  {
    "path": "builder/data/usr/bin/pwnlib",
    "content": "#!/usr/bin/env bash\n\n# well ... it blinks the led\nblink_led() {\n  for i in $(seq 1 \"$1\"); do\n    echo 0 >/sys/class/leds/led0/brightness\n    sleep 0.3\n    echo 1 >/sys/class/leds/led0/brightness\n    sleep 0.3\n  done\n  echo 0 >/sys/class/leds/led0/brightness\n  sleep 0.3\n}\n\n# check if brcm is stuck\ncheck_brcm() {\n  if [[ \"$(journalctl -n10 -k --since -5m | grep -c 'brcmf_cfg80211_nexmon_set_channel.*Set Channel failed')\" -ge 5 ]]; then\n    return 1\n  fi\n  return 0\n}\n\n# reload mod\nreload_brcm() {\n  if ! modprobe -r brcmfmac; then\n    return 1\n  fi\n  if ! modprobe brcmfmac; then\n    return 1\n  fi\n  return 0\n}\n\n# starts mon0\nstart_monitor_interface() {\n  iw phy \"$(iw phy | head -1 | cut -d\" \" -f2)\" interface add mon0 type monitor && ifconfig mon0 up\n}\n\n# stops mon0\nstop_monitor_interface() {\n  ifconfig mon0 down && iw dev mon0 del\n}\n\n# returns 0 if the specificed network interface is up\nis_interface_up() {\n  if grep -qi 'up' /sys/class/net/$1/operstate; then\n    return 0\n  fi\n  return 1\n}\n\n# returns 0 if conditions for AUTO mode are met\nis_auto_mode() {\n  # check override file first\n  if [ -f /root/.pwnagotchi-manual ]; then\n    # remove the override file if found\n    rm -rf /root/.pwnagotchi-manual\n    return 1\n  fi\n\n  # check override file first\n  if [ -f /root/.pwnagotchi-auto ]; then\n    # remove the override file if found\n    rm -rf /root/.pwnagotchi-auto\n    return 0\n  fi\n\n  # if usb0 is up, we're in MANU\n  if is_interface_up usb0; then\n    return 1\n  fi\n\n  # if eth0 is up (for other boards), we're in MANU\n  if is_interface_up eth0; then\n    return 1\n  fi\n\n  # no override, but none of the interfaces is up -> AUTO\n  return 0\n}\n\n# returns 0 if conditions for AUTO mode are met\nis_auto_mode_no_delete() {\n  # check override file first\n  if [ -f /root/.pwnagotchi-manual ]; then\n    return 1\n  fi\n\n  # check override file first\n  if [ -f /root/.pwnagotchi-auto ]; then\n    return 0\n  fi\n\n  # if usb0 is up, we're in MANU\n  if is_interface_up usb0; then\n    return 1\n  fi\n\n  # if eth0 is up (for other boards), we're in MANU\n  if is_interface_up eth0; then\n    return 1\n  fi\n\n  # no override, but none of the interfaces is up -> AUTO\n  return 0\n}\n\n# check if we need to decrypt something\nis_crypted_mode() {\n  if [ -f /root/.pwnagotchi-crypted ]; then\n    return 0\n  fi\n  return 1\n}\n\n# decryption loop\nis_decrypted() {\n  while read -r mapping container mount; do\n    # mapping   = name the device or file will be mapped to\n    # container = the luks encrypted device or file\n    # mount     = the mountpoint\n\n    # fail if not mounted\n    if ! mountpoint -q \"$mount\" >/dev/null 2>&1; then\n      if [ -f /tmp/.pwnagotchi-secret-\"$mapping\" ]; then\n        </tmp/.pwnagotchi-secret-\"$mapping\" read -r SECRET\n        if ! test -b /dev/disk/by-id/dm-uuid-*\"$(cryptsetup luksUUID \"$container\" | tr -d -)\"*; then\n          if echo -n \"$SECRET\" | cryptsetup luksOpen -d- \"$container\" \"$mapping\" >/dev/null 2>&1; then\n            echo \"Container decrypted!\"\n          fi\n        fi\n\n        if mount /dev/mapper/\"$mapping\" \"$mount\" >/dev/null 2>&1; then\n            echo \"Mounted /dev/mapper/$mapping to $mount\"\n            continue\n        fi\n      fi\n\n      if ! ip -4 addr show wlan0 | grep inet >/dev/null 2>&1; then\n        >/dev/null 2>&1 ip addr add 192.168.0.10/24 dev wlan0\n      fi\n\n      if ! pgrep -f decryption-webserver >/dev/null 2>&1; then\n        >/dev/null 2>&1 decryption-webserver &\n      fi\n\n      if ! pgrep wpa_supplicant >/dev/null 2>&1; then\n        >/tmp/wpa_supplicant.conf cat <<EOF\nctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\nupdate_config=1\nap_scan=2\n\nnetwork={\n    ssid=\"DECRYPT-ME\"\n    mode=2\n    key_mgmt=WPA-PSK\n    psk=\"pwnagotchi\"\n    frequency=2437\n}\nEOF\n        >/dev/null 2>&1 wpa_supplicant -u -s -O -D nl80211 -i wlan0 -c /tmp/wpa_supplicant.conf &\n      fi\n\n      if ! pgrep dnsmasq >/dev/null 2>&1; then\n        >/dev/null 2>&1 dnsmasq -k -p 53 -h -O \"6,192.168.0.10\" -A \"/#/192.168.0.10\" -i wlan0 -K -F 192.168.0.50,192.168.0.60,255.255.255.0,24h &\n      fi\n\n      return 1\n    fi\n  done </root/.pwnagotchi-crypted\n\n  # overwrite passwords\n  python3 -c 'print(\"A\"*4096)' | tee /tmp/.pwnagotchi-secret-* >/dev/null\n  # delete\n  rm /tmp/.pwnagotchi-secret-*\n  sync # flush\n\n  pkill wpa_supplicant\n  pkill dnsmasq\n  pid=\"$(pgrep -f \"decryption-webserver\")\"\n  [[ -n \"$pid\" ]] && kill \"$pid\"\n\n  return 0\n}\n"
  },
  {
    "path": "builder/pwnagotchi.json",
    "content": "{\n  \"builders\": [\n    {\n      \"name\": \"pwnagotchi\",\n      \"type\": \"arm-image\",\n      \"iso_url\": \"https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-07-12/2019-07-10-raspbian-buster-lite.zip\",\n      \"iso_checksum\": \"9e5cf24ce483bb96e7736ea75ca422e3560e7b455eee63dd28f66fa1825db70e\",\n      \"last_partition_extra_size\": 3221225472\n    }\n  ],\n  \"provisioners\": [\n    {\n      \"type\": \"shell\",\n      \"inline\": [\n        \"sed -i 's/^\\\\([^#]\\\\)/#\\\\1/g' /etc/ld.so.preload\",\n        \"dpkg-architecture\",\n        \"apt-get -y update\",\n        \"apt-get install -y ansible\"\n      ]\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/usr/bin/pwnlib\",\n      \"destination\": \"/usr/bin/pwnlib\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/usr/bin/bettercap-launcher\",\n      \"destination\": \"/usr/bin/bettercap-launcher\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/usr/bin/pwnagotchi-launcher\",\n      \"destination\": \"/usr/bin/pwnagotchi-launcher\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/usr/bin/monstop\",\n      \"destination\": \"/usr/bin/monstop\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/usr/bin/monstart\",\n      \"destination\": \"/usr/bin/monstart\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/usr/bin/hdmion\",\n      \"destination\": \"/usr/bin/hdmion\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/usr/bin/hdmioff\",\n      \"destination\": \"/usr/bin/hdmioff\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/etc/network/interfaces.d/lo-cfg\",\n      \"destination\": \"/etc/network/interfaces.d/lo-cfg\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/etc/network/interfaces.d/wlan0-cfg\",\n      \"destination\": \"/etc/network/interfaces.d/wlan0-cfg\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/etc/network/interfaces.d/usb0-cfg\",\n      \"destination\": \"/etc/network/interfaces.d/usb0-cfg\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/etc/network/interfaces.d/eth0-cfg\",\n      \"destination\": \"/etc/network/interfaces.d/eth0-cfg\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/etc/systemd/system/pwngrid-peer.service\",\n      \"destination\": \"/etc/systemd/system/pwngrid-peer.service\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/etc/systemd/system/pwnagotchi.service\",\n      \"destination\": \"/etc/systemd/system/pwnagotchi.service\"\n    },\n    {\n      \"type\": \"file\",\n      \"source\": \"data/etc/systemd/system/bettercap.service\",\n      \"destination\": \"/etc/systemd/system/bettercap.service\"\n    },\n    {\n      \"type\": \"shell\",\n      \"inline\": [\n        \"chmod +x /usr/bin/*\"\n      ]\n    },\n    {\n      \"type\": \"ansible-local\",\n      \"playbook_file\": \"pwnagotchi.yml\",\n      \"extra_arguments\": [ \"--extra-vars \\\"ansible_python_interpreter=/usr/bin/python3\\\"\" ],\n      \"command\": \"ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION={{user `pwn_version`}} PWN_HOSTNAME={{user `pwn_hostname`}} ansible-playbook\"\n    },\n    {\n      \"type\": \"shell\",\n      \"inline\": [\n        \"sed -i 's/^#\\\\(.+\\\\)/\\\\1/g' /etc/ld.so.preload\"\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "builder/pwnagotchi.yml",
    "content": "---\n- hosts:\n    - 127.0.0.1\n  become: yes\n  vars:\n    pwnagotchi:\n      hostname: \"{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}\"\n      version: \"{{ lookup('env', 'PWN_VERSION') | default('master', true) }}\"\n    system:\n      boot_options:\n        - \"dtoverlay=dwc2\"\n        - \"dtoverlay=spi1-3cs\"\n        - \"dtparam=spi=on\"\n        - \"dtparam=i2c_arm=on\"\n        - \"dtparam=i2c1=on\"\n        - \"gpu_mem=16\"\n      modules:\n        - \"i2c-dev\"\n    services:\n      enable:\n        - dphys-swapfile.service\n        - pwnagotchi.service\n        - bettercap.service\n        - pwngrid-peer.service\n        - epd-fuse.service\n        - fstrim.timer\n      disable:\n        - apt-daily.timer\n        - apt-daily.service\n        - apt-daily-upgrade.timer\n        - apt-daily-upgrade.service\n        - wpa_supplicant.service\n        - bluetooth.service\n        - triggerhappy.service\n        - ifup@wlan0.service\n        - dnsmasq.service\n    packages:\n      bettercap:\n        url: \"https://github.com/bettercap/bettercap/releases/download/v2.31.0/bettercap_linux_armhf_v2.31.0.zip\"\n        ui: \"https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip\"\n      pwngrid:\n        url: \"https://github.com/evilsocket/pwngrid/releases/download/v1.10.3/pwngrid_linux_armhf_v1.10.3.zip\"\n      apt:\n        hold:\n          - firmware-atheros\n          - firmware-brcm80211\n          - firmware-libertas\n          - firmware-misc-nonfree\n          - firmware-realtek\n        remove:\n          - raspberrypi-net-mods\n          - dhcpcd5\n          - triggerhappy\n          - wpa_supplicant\n          - nfs-common\n        install:\n          - rsync\n          - vim\n          - screen\n          - golang\n          - git\n          - build-essential\n          - python3-pip\n          - python3-mpi4py\n          - python3-smbus\n          - unzip\n          - gawk\n          - libopenmpi-dev\n          - libatlas-base-dev\n          - libjasper-dev\n          - libqtgui4\n          - libqt4-test\n          - libopenjp2-7\n          - libtiff5\n          - tcpdump\n          - lsof\n          - libilmbase23\n          - libopenexr23\n          - libgstreamer1.0-0\n          - libavcodec58\n          - libavformat58\n          - libswscale5\n          - libpcap-dev\n          - libusb-1.0-0-dev\n          - libnetfilter-queue-dev\n          - libopenmpi3\n          - dphys-swapfile\n          - kalipi-kernel\n          - kalipi-bootloader\n          - kalipi-re4son-firmware\n          - kalipi-kernel-headers\n          - libraspberrypi0\n          - libraspberrypi-dev\n          - libraspberrypi-doc\n          - libraspberrypi-bin\n          - fonts-dejavu\n          - fonts-dejavu-core\n          - fonts-dejavu-extra\n          - python3-pil\n          - python3-smbus\n          - libfuse-dev\n          - bc\n          - fonts-freefont-ttf\n          - fbi\n          - fonts-ipaexfont-gothic\n          - cryptsetup\n          - dnsmasq\n\n  tasks:\n  - name: change hostname\n    hostname:\n      name: \"{{pwnagotchi.hostname}}\"\n    when: lookup('file', '/etc/hostname') == \"raspberrypi\"\n    register: hostname\n\n  - name: add hostname to /etc/hosts\n    lineinfile:\n      dest: /etc/hosts\n      regexp: '^127\\.0\\.1\\.1[ \\t]+raspberrypi'\n      line: \"127.0.1.1\\t{{pwnagotchi.hostname}}\"\n      state: present\n    when: hostname.changed\n\n  - name: disable sap plugin for bluetooth.service\n    lineinfile:\n      dest: /lib/systemd/system/bluetooth.service\n      regexp: '^ExecStart=/usr/lib/bluetooth/bluetoothd$'\n      line: 'ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap'\n      state: present\n\n  - name: Add re4son-kernel repo key\n    apt_key:\n      url: https://re4son-kernel.com/keys/http/archive-key.asc\n      state: present\n\n  - name: Add re4son-kernel repository\n    apt_repository:\n      repo: deb http://http.re4son-kernel.com/re4son/ kali-pi main\n      state: present\n\n  - name: create /etc/apt/preferences.d/kali.pref\n    copy:\n      dest: /etc/apt/preferences.d/kali.pref\n      force: yes\n      content: |\n        # ensure kali packages that are installed take precedence\n        Package: *\n        Pin: release n=kali-pi\n        Pin-Priority: 999\n\n  - name: add firmware packages to hold\n    dpkg_selections:\n      name: \"{{ item }}\"\n      selection: hold\n    with_items: \"{{ packages.apt.hold }}\"\n\n  - name: update apt package cache\n    apt:\n      update_cache: yes\n\n  - name: remove unecessary apt packages\n    apt:\n      name: \"{{ packages.apt.remove }}\"\n      state: absent\n      purge: yes\n\n  - name: upgrade apt distro\n    apt:\n      upgrade: dist\n\n  - name: install packages\n    apt:\n      name: \"{{ packages.apt.install }}\"\n      state: present\n\n  - name: configure dphys-swapfile\n    file:\n      path: /etc/dphys-swapfile\n      content: \"CONF_SWAPSIZE=1024\"\n\n  - name: clone papirus repository\n    git:\n      repo: https://github.com/repaper/gratis.git\n      dest: /usr/local/src/gratis\n    register: gratisgit\n\n  - name: build papirus service\n    make:\n      chdir: /usr/local/src/gratis\n      target: rpi\n      params:\n        EPD_IO: epd_io_free_uart.h\n        PANEL_VERSION: 'V231_G2'\n    when: gratisgit.changed\n\n  - name: install papirus service\n    make:\n      chdir: /usr/local/src/gratis\n      target: rpi-install\n      params:\n        EPD_IO: epd_io_free_uart.h\n        PANEL_VERSION: 'V231_G2'\n    when: gratisgit.changed\n\n  - name: configure papirus display size\n    lineinfile:\n      dest: /etc/default/epd-fuse\n      regexp: \"#EPD_SIZE=2.0\"\n      line: \"EPD_SIZE=2.0\"\n\n  - name: collect python pip package list\n    command: \"pip3 list\"\n    register: pip_output\n\n  - name: set python pip package facts\n    set_fact:\n      pip_packages: >\n        {{ pip_packages | default({}) | combine( { item.split()[0]: item.split()[1] } ) }}\n    with_items: \"{{ pip_output.stdout_lines }}\"\n\n  - name: acquire python3 pip target\n    command: \"python3 -c 'import sys;print(sys.path.pop())'\"\n    register: pip_target\n\n  - name: clone pwnagotchi repository\n    git:\n      repo: https://github.com/evilsocket/pwnagotchi.git\n      dest: /usr/local/src/pwnagotchi\n    register: pwnagotchigit\n\n  - name: create /usr/local/share/pwnagotchi/ folder\n    file:\n      path: /usr/local/share/pwnagotchi/\n      state: directory\n\n  - name: clone pwnagotchi plugins repository\n    git:\n      repo: https://github.com/evilsocket/pwnagotchi-plugins-contrib.git\n      dest: /usr/local/share/pwnagotchi/availaible-plugins\n\n  - name: fetch pwnagotchi version\n    set_fact:\n      pwnagotchi_version: \"{{ lookup('file', '/usr/local/src/pwnagotchi/pwnagotchi/_version.py') | regex_replace('.*__version__.*=.*''([0-9]+\\\\.[0-9]+\\\\.[0-9]+[A-Za-z0-9]*)''.*', '\\\\1') }}\"\n\n  - name: pwnagotchi version found\n    debug:\n      msg: \"{{ pwnagotchi_version }}\"\n\n  - name: build pwnagotchi wheel\n    command: \"python3 setup.py sdist bdist_wheel\"\n    args:\n      chdir: /usr/local/src/pwnagotchi\n    when: (pwnagotchigit.changed) or (pip_packages['pwnagotchi'] is undefined) or (pip_packages['pwnagotchi'] != pwnagotchi_version)\n\n  - name: install opencv-python\n    pip:\n      name: \"https://www.piwheels.org/simple/opencv-python/opencv_python-3.4.3.18-cp37-cp37m-linux_armv6l.whl\"\n      extra_args: \"--no-deps --no-cache-dir --platform=linux_armv6l --only-binary=:all: --target={{ pip_target.stdout }}\"\n    when: (pip_packages['opencv-python'] is undefined) or (pip_packages['opencv-python'] != '3.4.3.18')\n\n  - name: install tensorflow\n    pip:\n      name: \"https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl\"\n      extra_args: \"--no-deps --no-cache-dir --platform=linux_armv6l --only-binary=:all: --target={{ pip_target.stdout }}\"\n    when: (pip_packages['tensorflow'] is undefined) or (pip_packages['tensorflow'] != '1.13.1')\n\n  - name: install pwnagotchi wheel and dependencies\n    pip:\n      name: \"{{ lookup('fileglob', '/usr/local/src/pwnagotchi/dist/pwnagotchi*.whl') }}\"\n      extra_args: \"--no-cache-dir\"\n    when: (pwnagotchigit.changed) or (pip_packages['pwnagotchi'] is undefined) or (pip_packages['pwnagotchi'] != pwnagotchi_version)\n\n  - name: download and install pwngrid\n    unarchive:\n      src: \"{{ packages.pwngrid.url }}\"\n      dest: /usr/bin\n      remote_src: yes\n      mode: 0755\n\n  - name: download and install bettercap\n    unarchive:\n      src: \"{{ packages.bettercap.url }}\"\n      dest: /usr/bin\n      remote_src: yes\n      exclude:\n        - README.md\n        - LICENSE.md\n      mode: 0755\n\n  - name: clone bettercap caplets\n    git:\n      repo: https://github.com/bettercap/caplets.git\n      dest: /tmp/caplets\n    register: capletsgit\n\n  - name: install bettercap caplets\n    make:\n      chdir: /tmp/caplets\n      target: install\n    when: capletsgit.changed\n\n  - name: download and install bettercap ui\n    unarchive:\n      src: \"{{ packages.bettercap.ui }}\"\n      dest: /usr/local/share/bettercap/\n      remote_src: yes\n      mode: 0755\n\n  - name: add HDMI powersave to rc.local\n    blockinfile:\n      path: /etc/rc.local\n      insertbefore: \"exit 0\"\n      block: |\n        if ! /opt/vc/bin/tvservice -s | egrep 'HDMI|DVI'; then\n          /opt/vc/bin/tvservice -o\n        fi\n\n  - name: create /etc/pwnagotchi folder\n    file:\n      path: /etc/pwnagotchi\n      state: directory\n\n  - name: check if user configuration exists\n    stat:\n      path: /etc/pwnagotchi/config.toml\n    register: user_config\n\n  - name: create /etc/pwnagotchi/config.toml\n    copy:\n      dest: /etc/pwnagotchi/config.toml\n      content: |\n        # Add your configuration overrides on this file any configuration changes done to default.toml will be lost!\n        # Example:\n        # ui.display.enabled = true\n        # ui.display.type = \"waveshare_2\"\n    when: not user_config.stat.exists\n\n  - name: enable ssh on boot\n    file:\n      path: /boot/ssh\n      state: touch\n\n  - name: adjust /boot/config.txt\n    lineinfile:\n      dest: /boot/config.txt\n      insertafter: EOF\n      line: '{{ item }}'\n    with_items: \"{{system.boot_options}}\"\n\n  - name: adjust /etc/modules\n    lineinfile:\n      dest: /etc/modules\n      insertafter: EOF\n      line: '{{ item }}'\n    with_items: \"{{system.modules}}\"\n\n  - name: change root partition\n    replace:\n      dest: /boot/cmdline.txt\n      backup: no\n      regexp: \"root=PARTUUID=[a-zA-Z0-9\\\\-]+\"\n      replace: \"root=/dev/mmcblk0p2\"\n\n  - name: configure /boot/cmdline.txt\n    lineinfile:\n      path: /boot/cmdline.txt\n      backrefs: True\n      state: present\n      backup: no\n      regexp: '(.*)$'\n      line: '\\1 modules-load=dwc2,g_ether'\n\n  - name: configure motd\n    copy:\n      dest: /etc/motd\n      content: |\n        (◕‿‿◕) {{pwnagotchi.hostname}}\n\n        Hi! I'm a pwnagotchi, please take good care of me!\n        Here are some basic things you need to know to raise me properly!\n\n        If you want to change my configuration, use /etc/pwnagotchi/config.toml\n\n        All the configuration options can be found on /etc/pwnagotchi/default.toml,\n        but don't change this file because I will recreate it every time I'm restarted!\n\n        I'm managed by systemd. Here are some basic commands.\n\n        If you want to know what I'm doing, you can check my logs with the command\n        tail -f /var/log/pwnagotchi.log\n\n        If you want to know if I'm running, you can use\n        systemctl status pwnagotchi\n\n        You can restart me using\n        systemctl restart pwnagotchi\n\n        But be aware I will go into MANUAL mode when restarted!\n        You can put me back into AUTO mode using\n        touch /root/.pwnagotchi-auto && systemctl restart pwnagotchi\n\n        You learn more about me at https://pwnagotchi.ai/\n    when: hostname.changed\n\n  - name: clean apt cache\n    apt:\n      autoclean: yes\n\n  - name: remove dependencies that are no longer required\n    apt:\n      autoremove: yes\n\n  - name: enable services\n    systemd:\n      name: \"{{ item }}\"\n      state: started\n      enabled: yes\n    with_items: \"{{ services.enable }}\"\n\n  - name: disable unecessary services\n    systemd:\n      name: \"{{ item }}\"\n      state: stopped\n      enabled: no\n    with_items: \"{{ services.disable }}\"\n\n  - name: remove ssh keys\n    file:\n      state: absent\n      path: \"{{item}}\"\n    with_fileglob:\n      - \"/etc/ssh/ssh_host*_key*\"\n\n  handlers:\n  - name: reload systemd services\n    systemd:\n      daemon_reload: yes\n"
  },
  {
    "path": "pwnagotchi/__init__.py",
    "content": "import os\nimport logging\nimport time\nimport re\n\n\n\nfrom pwnagotchi._version import __version__\n\n_name = None\nconfig = None\n\n\ndef set_name(new_name):\n    if new_name is None:\n        return\n\n    new_name = new_name.strip()\n    if new_name == '':\n        return\n\n    if not re.match(r'^[a-zA-Z0-9\\-]{2,25}$', new_name):\n        logging.warning(\"name '%s' is invalid: min length is 2, max length 25, only a-zA-Z0-9- allowed\", new_name)\n        return\n\n    current = name()\n    if new_name != current:\n        global _name\n\n        logging.info(\"setting unit hostname '%s' -> '%s'\", current, new_name)\n        with open('/etc/hostname', 'wt') as fp:\n            fp.write(new_name)\n\n        with open('/etc/hosts', 'rt') as fp:\n            prev = fp.read()\n            logging.debug(\"old hosts:\\n%s\\n\", prev)\n\n        with open('/etc/hosts', 'wt') as fp:\n            patched = prev.replace(current, new_name, -1)\n            logging.debug(\"new hosts:\\n%s\\n\", patched)\n            fp.write(patched)\n\n        os.system(\"hostname '%s'\" % new_name)\n        pwnagotchi.reboot()\n\n\ndef name():\n    global _name\n    if _name is None:\n        with open('/etc/hostname', 'rt') as fp:\n            _name = fp.read().strip()\n    return _name\n\n\ndef uptime():\n    with open('/proc/uptime') as fp:\n        return int(fp.read().split('.')[0])\n\n\ndef mem_usage():\n    with open('/proc/meminfo') as fp:\n        for line in fp:\n            line = line.strip()\n            if line.startswith(\"MemTotal:\"):\n                kb_mem_total = int(line.split()[1])\n            if line.startswith(\"MemFree:\"):\n                kb_mem_free = int(line.split()[1])\n            if line.startswith(\"Buffers:\"):\n                kb_main_buffers = int(line.split()[1])\n            if line.startswith(\"Cached:\"):\n                kb_main_cached = int(line.split()[1])\n        kb_mem_used = kb_mem_total - kb_mem_free - kb_main_cached - kb_main_buffers\n        return round(kb_mem_used / kb_mem_total, 1)\n\n    return 0\n\n\ndef _cpu_stat():\n    \"\"\"\n    Returns the splitted first line of the /proc/stat file\n    \"\"\"\n    with open('/proc/stat', 'rt') as fp:\n        return list(map(int,fp.readline().split()[1:]))\n\n\ndef cpu_load():\n    \"\"\"\n    Returns the current cpuload\n    \"\"\"\n    parts0 = _cpu_stat()\n    time.sleep(0.1)\n    parts1 = _cpu_stat()\n    parts_diff = [p1 - p0 for (p0, p1) in zip(parts0, parts1)]\n    user, nice, sys, idle, iowait, irq, softirq, steal, _guest, _guest_nice = parts_diff\n    idle_sum = idle + iowait\n    non_idle_sum = user + nice + sys + irq + softirq + steal\n    total = idle_sum + non_idle_sum\n    return non_idle_sum / total\n\n\ndef temperature(celsius=True):\n    with open('/sys/class/thermal/thermal_zone0/temp', 'rt') as fp:\n        temp = int(fp.read().strip())\n    c = int(temp / 1000)\n    return c if celsius else ((c * (9 / 5)) + 32)\n\n\ndef shutdown():\n    logging.warning(\"shutting down ...\")\n\n    from pwnagotchi.ui import view\n    if view.ROOT:\n        view.ROOT.on_shutdown()\n        # give it some time to refresh the ui\n        time.sleep(10)\n\n    logging.warning(\"syncing...\")\n\n    from pwnagotchi import fs\n    for m in fs.mounts:\n        m.sync()\n \n    os.system(\"sync\")\n    os.system(\"halt\")\n\n\ndef restart(mode):\n    logging.warning(\"restarting in %s mode ...\", mode)\n\n    if mode == 'AUTO':\n        os.system(\"touch /root/.pwnagotchi-auto\")\n    else:\n        os.system(\"touch /root/.pwnagotchi-manual\")\n\n    os.system(\"service bettercap restart\")\n    os.system(\"service pwnagotchi restart\")\n\n\ndef reboot(mode=None):\n    if mode is not None:\n        mode = mode.upper()\n        logging.warning(\"rebooting in %s mode ...\", mode)\n    else:\n        logging.warning(\"rebooting ...\")\n\n    from pwnagotchi.ui import view\n    if view.ROOT:\n        view.ROOT.on_rebooting()\n        # give it some time to refresh the ui\n        time.sleep(10)\n\n    if mode == 'AUTO':\n        os.system(\"touch /root/.pwnagotchi-auto\")\n    elif mode == 'MANU':\n        os.system(\"touch /root/.pwnagotchi-manual\")\n\n    logging.warning(\"syncing...\")\n\n    from pwnagotchi import fs\n    for m in fs.mounts:\n        m.sync()\n\n    os.system(\"sync\")\n    os.system(\"shutdown -r now\")\n"
  },
  {
    "path": "pwnagotchi/_version.py",
    "content": "__version__ = '1.5.5'\n"
  },
  {
    "path": "pwnagotchi/agent.py",
    "content": "import time\nimport json\nimport os\nimport re\nimport logging\nimport asyncio\nimport _thread\n\nimport pwnagotchi\nimport pwnagotchi.utils as utils\nimport pwnagotchi.plugins as plugins\nfrom pwnagotchi.ui.web.server import Server\nfrom pwnagotchi.automata import Automata\nfrom pwnagotchi.log import LastSession\nfrom pwnagotchi.bettercap import Client\nfrom pwnagotchi.mesh.utils import AsyncAdvertiser\nfrom pwnagotchi.ai.train import AsyncTrainer\n\nRECOVERY_DATA_FILE = '/root/.pwnagotchi-recovery'\n\n\nclass Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):\n    def __init__(self, view, config, keypair):\n        Client.__init__(self, config['bettercap']['hostname'],\n                        config['bettercap']['scheme'],\n                        config['bettercap']['port'],\n                        config['bettercap']['username'],\n                        config['bettercap']['password'])\n        Automata.__init__(self, config, view)\n        AsyncAdvertiser.__init__(self, config, view, keypair)\n        AsyncTrainer.__init__(self, config)\n\n        self._started_at = time.time()\n        self._filter = None if not config['main']['filter'] else re.compile(config['main']['filter'])\n        self._current_channel = 0\n        self._tot_aps = 0\n        self._aps_on_channel = 0\n        self._supported_channels = utils.iface_channels(config['main']['iface'])\n        self._view = view\n        self._view.set_agent(self)\n        self._web_ui = Server(self, config['ui'])\n\n        self._access_points = []\n        self._last_pwnd = None\n        self._history = {}\n        self._handshakes = {}\n        self.last_session = LastSession(self._config)\n        self.mode = 'auto'\n\n        if not os.path.exists(config['bettercap']['handshakes']):\n            os.makedirs(config['bettercap']['handshakes'])\n\n        logging.info(\"%s@%s (v%s)\", pwnagotchi.name(), self.fingerprint(), pwnagotchi.__version__)\n        for _, plugin in plugins.loaded.items():\n            logging.debug(\"plugin '%s' v%s\", plugin.__class__.__name__, plugin.__version__)\n\n    def config(self):\n        return self._config\n\n    def view(self):\n        return self._view\n\n    def supported_channels(self):\n        return self._supported_channels\n\n    def setup_events(self):\n        logging.info(\"connecting to %s ...\", self.url)\n\n        for tag in self._config['bettercap']['silence']:\n            try:\n                self.run('events.ignore %s' % tag, verbose_errors=False)\n            except Exception:\n                pass\n\n    def _reset_wifi_settings(self):\n        mon_iface = self._config['main']['iface']\n        self.run('set wifi.interface %s' % mon_iface)\n        self.run('set wifi.ap.ttl %d' % self._config['personality']['ap_ttl'])\n        self.run('set wifi.sta.ttl %d' % self._config['personality']['sta_ttl'])\n        self.run('set wifi.rssi.min %d' % self._config['personality']['min_rssi'])\n        self.run('set wifi.handshakes.file %s' % self._config['bettercap']['handshakes'])\n        self.run('set wifi.handshakes.aggregate false')\n\n    def start_monitor_mode(self):\n        mon_iface = self._config['main']['iface']\n        mon_start_cmd = self._config['main']['mon_start_cmd']\n        restart = not self._config['main']['no_restart']\n        has_mon = False\n\n        while has_mon is False:\n            s = self.session()\n            for iface in s['interfaces']:\n                if iface['name'] == mon_iface:\n                    logging.info(\"found monitor interface: %s\", iface['name'])\n                    has_mon = True\n                    break\n\n            if has_mon is False:\n                if mon_start_cmd is not None and mon_start_cmd != '':\n                    logging.info(\"starting monitor interface ...\")\n                    self.run('!%s' % mon_start_cmd)\n                else:\n                    logging.info(\"waiting for monitor interface %s ...\", mon_iface)\n                    time.sleep(1)\n\n        logging.info(\"supported channels: %s\", self._supported_channels)\n        logging.info(\"handshakes will be collected inside %s\", self._config['bettercap']['handshakes'])\n\n        self._reset_wifi_settings()\n\n        wifi_running = self.is_module_running('wifi')\n        if wifi_running and restart:\n            logging.debug(\"restarting wifi module ...\")\n            self.restart_module('wifi.recon')\n            self.run('wifi.clear')\n        elif not wifi_running:\n            logging.debug(\"starting wifi module ...\")\n            self.start_module('wifi.recon')\n\n        self.start_advertising()\n\n    def _wait_bettercap(self):\n        while True:\n            try:\n                _s = self.session()\n                return\n            except Exception:\n                logging.info(\"waiting for bettercap API to be available ...\")\n                time.sleep(1)\n\n    def start(self):\n        self.start_ai()\n        self._wait_bettercap()\n        self.setup_events()\n        self.set_starting()\n        self.start_monitor_mode()\n        self.start_event_polling()\n        self.start_session_fetcher()\n        # print initial stats\n        self.next_epoch()\n        self.set_ready()\n\n    def recon(self):\n        recon_time = self._config['personality']['recon_time']\n        max_inactive = self._config['personality']['max_inactive_scale']\n        recon_mul = self._config['personality']['recon_inactive_multiplier']\n        channels = self._config['personality']['channels']\n\n        if self._epoch.inactive_for >= max_inactive:\n            recon_time *= recon_mul\n\n        self._view.set('channel', '*')\n\n        if not channels:\n            self._current_channel = 0\n            logging.debug(\"RECON %ds\", recon_time)\n            self.run('wifi.recon.channel clear')\n        else:\n            logging.debug(\"RECON %ds ON CHANNELS %s\", recon_time, ','.join(map(str, channels)))\n            try:\n                self.run('wifi.recon.channel %s' % ','.join(map(str, channels)))\n            except Exception as e:\n                logging.exception(\"Error while setting wifi.recon.channels (%s)\", e)\n\n        self.wait_for(recon_time, sleeping=False)\n\n    def _filter_included(self, ap):\n        return self._filter is None or \\\n               self._filter.match(ap['hostname']) is not None or \\\n               self._filter.match(ap['mac']) is not None\n\n    def set_access_points(self, aps):\n        self._access_points = aps\n        plugins.on('wifi_update', self, aps)\n        self._epoch.observe(aps, list(self._peers.values()))\n        return self._access_points\n\n    def get_access_points(self):\n        whitelist = self._config['main']['whitelist']\n        aps = []\n        try:\n            s = self.session()\n            plugins.on(\"unfiltered_ap_list\", self, s['wifi']['aps'])\n            for ap in s['wifi']['aps']:\n                if ap['encryption'] == '' or ap['encryption'] == 'OPEN':\n                    continue\n                elif ap['hostname'] not in whitelist \\\n                        and ap['mac'].lower() not in whitelist \\\n                        and ap['mac'][:8].lower() not in whitelist:\n                    if self._filter_included(ap):\n                        aps.append(ap)\n        except Exception as e:\n            logging.exception(\"Error while getting acces points (%s)\", e)\n\n        aps.sort(key=lambda ap: ap['channel'])\n        return self.set_access_points(aps)\n\n    def get_total_aps(self):\n        return self._tot_aps\n\n    def get_aps_on_channel(self):\n        return self._aps_on_channel\n\n    def get_current_channel(self):\n        return self._current_channel\n\n    def get_access_points_by_channel(self):\n        aps = self.get_access_points()\n        channels = self._config['personality']['channels']\n        grouped = {}\n\n        # group by channel\n        for ap in aps:\n            ch = ap['channel']\n            # if we're sticking to a channel, skip anything\n            # which is not on that channel\n            if channels and ch not in channels:\n                continue\n\n            if ch not in grouped:\n                grouped[ch] = [ap]\n            else:\n                grouped[ch].append(ap)\n\n        # sort by more populated channels\n        return sorted(grouped.items(), key=lambda kv: len(kv[1]), reverse=True)\n\n    def _find_ap_sta_in(self, station_mac, ap_mac, session):\n        for ap in session['wifi']['aps']:\n            if ap['mac'] == ap_mac:\n                for sta in ap['clients']:\n                    if sta['mac'] == station_mac:\n                        return (ap, sta)\n                return (ap, {'mac': station_mac, 'vendor': ''})\n        return None\n\n    def _update_uptime(self, s):\n        secs = pwnagotchi.uptime()\n        self._view.set('uptime', utils.secs_to_hhmmss(secs))\n        # self._view.set('epoch', '%04d' % self._epoch.epoch)\n\n    def _update_counters(self):\n        self._tot_aps = len(self._access_points)\n        tot_stas = sum(len(ap['clients']) for ap in self._access_points)\n        if self._current_channel == 0:\n            self._view.set('aps', '%d' % self._tot_aps)\n            self._view.set('sta', '%d' % tot_stas)\n        else:\n            self._aps_on_channel = len([ap for ap in self._access_points if ap['channel'] == self._current_channel])\n            stas_on_channel = sum(\n                [len(ap['clients']) for ap in self._access_points if ap['channel'] == self._current_channel])\n            self._view.set('aps', '%d (%d)' % (self._aps_on_channel, self._tot_aps))\n            self._view.set('sta', '%d (%d)' % (stas_on_channel, tot_stas))\n\n    def _update_handshakes(self, new_shakes=0):\n        if new_shakes > 0:\n            self._epoch.track(handshake=True, inc=new_shakes)\n\n        tot = utils.total_unique_handshakes(self._config['bettercap']['handshakes'])\n        txt = '%d (%d)' % (len(self._handshakes), tot)\n\n        if self._last_pwnd is not None:\n            txt += ' [%s]' % self._last_pwnd[:20]\n\n        self._view.set('shakes', txt)\n\n        if new_shakes > 0:\n            self._view.on_handshakes(new_shakes)\n\n    def _update_peers(self):\n        self._view.set_closest_peer(self._closest_peer, len(self._peers))\n\n    def _reboot(self):\n        self.set_rebooting()\n        self._save_recovery_data()\n        pwnagotchi.reboot()\n\n    def _save_recovery_data(self):\n        logging.warning(\"writing recovery data to %s ...\", RECOVERY_DATA_FILE)\n        with open(RECOVERY_DATA_FILE, 'w') as fp:\n            data = {\n                'started_at': self._started_at,\n                'epoch': self._epoch.epoch,\n                'history': self._history,\n                'handshakes': self._handshakes,\n                'last_pwnd': self._last_pwnd\n            }\n            json.dump(data, fp)\n\n    def _load_recovery_data(self, delete=True, no_exceptions=True):\n        try:\n            with open(RECOVERY_DATA_FILE, 'rt') as fp:\n                data = json.load(fp)\n                logging.info(\"found recovery data: %s\", data)\n                self._started_at = data['started_at']\n                self._epoch.epoch = data['epoch']\n                self._handshakes = data['handshakes']\n                self._history = data['history']\n                self._last_pwnd = data['last_pwnd']\n\n                if delete:\n                    logging.info(\"deleting %s\", RECOVERY_DATA_FILE)\n                    os.unlink(RECOVERY_DATA_FILE)\n        except:\n            if not no_exceptions:\n                raise\n\n\n    def start_session_fetcher(self):\n        _thread.start_new_thread(self._fetch_stats, ())\n\n\n    def _fetch_stats(self):\n        while True:\n            s = self.session()\n            self._update_uptime(s)\n            self._update_advertisement(s)\n            self._update_peers()\n            self._update_counters()\n            self._update_handshakes(0)\n            time.sleep(1)\n\n    async def _on_event(self, msg):\n        found_handshake = False\n        jmsg = json.loads(msg)\n\n        if jmsg['tag'] == 'wifi.client.handshake':\n            filename = jmsg['data']['file']\n            sta_mac = jmsg['data']['station']\n            ap_mac = jmsg['data']['ap']\n            key = \"%s -> %s\" % (sta_mac, ap_mac)\n            if key not in self._handshakes:\n                self._handshakes[key] = jmsg\n                s = self.session()\n                ap_and_station = self._find_ap_sta_in(sta_mac, ap_mac, s)\n                if ap_and_station is None:\n                    logging.warning(\"!!! captured new handshake: %s !!!\", key)\n                    self._last_pwnd = ap_mac\n                    plugins.on('handshake', self, filename, ap_mac, sta_mac)\n                else:\n                    (ap, sta) = ap_and_station\n                    self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap[\n                        'hostname'] != '<hidden>' else ap_mac\n                    logging.warning(\n                        \"!!! captured new handshake on channel %d, %d dBm: %s (%s) -> %s [%s (%s)] !!!\",\n                            ap['channel'],\n                            ap['rssi'],\n                            sta['mac'], sta['vendor'],\n                            ap['hostname'], ap['mac'], ap['vendor'])\n                    plugins.on('handshake', self, filename, ap, sta)\n                found_handshake = True\n            self._update_handshakes(1 if found_handshake else 0)\n\n    def _event_poller(self, loop):\n        self._load_recovery_data()\n        self.run('events.clear')\n\n        while True:\n            logging.debug(\"polling events ...\")\n            try:\n                loop.create_task(self.start_websocket(self._on_event))\n                loop.run_forever()\n            except Exception as ex:\n                logging.debug(\"Error while polling via websocket (%s)\", ex)\n\n    def start_event_polling(self):\n        # start a thread and pass in the mainloop\n        _thread.start_new_thread(self._event_poller, (asyncio.get_event_loop(),))\n\n\n    def is_module_running(self, module):\n        s = self.session()\n        for m in s['modules']:\n            if m['name'] == module:\n                return m['running']\n        return False\n\n    def start_module(self, module):\n        self.run('%s on' % module)\n\n    def restart_module(self, module):\n        self.run('%s off; %s on' % (module, module))\n\n    def _has_handshake(self, bssid):\n        for key in self._handshakes:\n            if bssid.lower() in key:\n                return True\n        return False\n\n    def _should_interact(self, who):\n        if self._has_handshake(who):\n            return False\n\n        elif who not in self._history:\n            self._history[who] = 1\n            return True\n\n        else:\n            self._history[who] += 1\n\n        return self._history[who] < self._config['personality']['max_interactions']\n\n    def associate(self, ap, throttle=0):\n        if self.is_stale():\n            logging.debug(\"recon is stale, skipping assoc(%s)\", ap['mac'])\n            return\n\n        if self._config['personality']['associate'] and self._should_interact(ap['mac']):\n            self._view.on_assoc(ap)\n\n            try:\n                logging.info(\"sending association frame to %s (%s %s) on channel %d [%d clients], %d dBm...\",\n                    ap['hostname'], ap['mac'], ap['vendor'], ap['channel'], len(ap['clients']), ap['rssi'])\n                self.run('wifi.assoc %s' % ap['mac'])\n                self._epoch.track(assoc=True)\n            except Exception as e:\n                self._on_error(ap['mac'], e)\n\n            plugins.on('association', self, ap)\n            if throttle > 0:\n                time.sleep(throttle)\n            self._view.on_normal()\n\n    def deauth(self, ap, sta, throttle=0):\n        if self.is_stale():\n            logging.debug(\"recon is stale, skipping deauth(%s)\", sta['mac'])\n            return\n\n        if self._config['personality']['deauth'] and self._should_interact(sta['mac']):\n            self._view.on_deauth(sta)\n\n            try:\n                logging.info(\"deauthing %s (%s) from %s (%s %s) on channel %d, %d dBm ...\",\n                    sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'], ap['channel'], ap['rssi'])\n                self.run('wifi.deauth %s' % sta['mac'])\n                self._epoch.track(deauth=True)\n            except Exception as e:\n                self._on_error(sta['mac'], e)\n\n            plugins.on('deauthentication', self, ap, sta)\n            if throttle > 0:\n                time.sleep(throttle)\n            self._view.on_normal()\n\n    def set_channel(self, channel, verbose=True):\n        if self.is_stale():\n            logging.debug(\"recon is stale, skipping set_channel(%d)\", channel)\n            return\n\n        # if in the previous loop no client stations has been deauthenticated\n        # and only association frames have been sent, we don't need to wait\n        # very long before switching channel as we don't have to wait for\n        # such client stations to reconnect in order to sniff the handshake.\n        wait = 0\n        if self._epoch.did_deauth:\n            wait = self._config['personality']['hop_recon_time']\n        elif self._epoch.did_associate:\n            wait = self._config['personality']['min_recon_time']\n\n        if channel != self._current_channel:\n            if self._current_channel != 0 and wait > 0:\n                if verbose:\n                    logging.info(\"waiting for %ds on channel %d ...\", wait, self._current_channel)\n                else:\n                    logging.debug(\"waiting for %ds on channel %d ...\", wait, self._current_channel)\n                self.wait_for(wait)\n            if verbose and self._epoch.any_activity:\n                logging.info(\"CHANNEL %d\", channel)\n            try:\n                self.run('wifi.recon.channel %d' % channel)\n                self._current_channel = channel\n                self._epoch.track(hop=True)\n                self._view.set('channel', '%d' % channel)\n\n                plugins.on('channel_hop', self, channel)\n\n            except Exception as e:\n                logging.error(\"Error while setting channel (%s)\", e)\n"
  },
  {
    "path": "pwnagotchi/ai/__init__.py",
    "content": "import os\nimport time\nimport logging\n\n# https://stackoverflow.com/questions/40426502/is-there-a-way-to-suppress-the-messages-tensorflow-prints/40426709\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'  # or any {'0', '1', '2'}\n\n\ndef load(config, agent, epoch, from_disk=True):\n    config = config['ai']\n    if not config['enabled']:\n        logging.info(\"ai disabled\")\n        return False\n\n    try:\n        begin = time.time()\n\n        logging.info(\"[ai] bootstrapping dependencies ...\")\n\n        start = time.time()\n        from stable_baselines import A2C\n        logging.debug(\"[ai] A2C imported in %.2fs\" % (time.time() - start))\n\n        start = time.time()\n        from stable_baselines.common.policies import MlpLstmPolicy\n        logging.debug(\"[ai] MlpLstmPolicy imported in %.2fs\" % (time.time() - start))\n\n        start = time.time()\n        from stable_baselines.common.vec_env import DummyVecEnv\n        logging.debug(\"[ai] DummyVecEnv imported in %.2fs\" % (time.time() - start))\n\n        start = time.time()\n        import pwnagotchi.ai.gym as wrappers\n        logging.debug(\"[ai] gym wrapper imported in %.2fs\" % (time.time() - start))\n\n        env = wrappers.Environment(agent, epoch)\n        env = DummyVecEnv([lambda: env])\n\n        logging.info(\"[ai] creating model ...\")\n\n        start = time.time()\n        a2c = A2C(MlpLstmPolicy, env, **config['params'])\n        logging.debug(\"[ai] A2C created in %.2fs\" % (time.time() - start))\n\n        if from_disk and os.path.exists(config['path']):\n            logging.info(\"[ai] loading %s ...\" % config['path'])\n            start = time.time()\n            a2c.load(config['path'], env)\n            logging.debug(\"[ai] A2C loaded in %.2fs\" % (time.time() - start))\n        else:\n            logging.info(\"[ai] model created:\")\n            for key, value in config['params'].items():\n                logging.info(\"      %s: %s\" % (key, value))\n\n        logging.debug(\"[ai] total loading time is %.2fs\" % (time.time() - begin))\n\n        return a2c\n    except Exception as e:\n        logging.exception(\"error while starting AI (%s)\", e)\n\n    logging.warning(\"[ai] AI not loaded!\")\n    return False\n"
  },
  {
    "path": "pwnagotchi/ai/epoch.py",
    "content": "import time\nimport threading\nimport logging\n\nimport pwnagotchi\nimport pwnagotchi.utils as utils\nimport pwnagotchi.mesh.wifi as wifi\n\nfrom pwnagotchi.ai.reward import RewardFunction\n\n\nclass Epoch(object):\n    def __init__(self, config):\n        self.epoch = 0\n        self.config = config\n        # how many consecutive epochs with no activity\n        self.inactive_for = 0\n        # how many consecutive epochs with activity\n        self.active_for = 0\n        # number of epochs with no visible access points\n        self.blind_for = 0\n        # number of epochs in sad state\n        self.sad_for = 0\n        # number of epochs in bored state\n        self.bored_for = 0\n        # did deauth in this epoch in the current channel?\n        self.did_deauth = False\n        # number of deauths in this epoch\n        self.num_deauths = 0\n        # did associate in this epoch in the current channel?\n        self.did_associate = False\n        # number of associations in this epoch\n        self.num_assocs = 0\n        # number of assocs or deauths missed\n        self.num_missed = 0\n        # did get any handshake in this epoch?\n        self.did_handshakes = False\n        # number of handshakes captured in this epoch\n        self.num_shakes = 0\n        # number of channels hops\n        self.num_hops = 0\n        # number of seconds sleeping\n        self.num_slept = 0\n        # number of peers seen during this epoch\n        self.num_peers = 0\n        # cumulative bond factor\n        self.tot_bond_factor = 0.0  # cum_bond_factor sounded really bad ...\n        # average bond factor\n        self.avg_bond_factor = 0.0\n        # any activity at all during this epoch?\n        self.any_activity = False\n        # when the current epoch started\n        self.epoch_started = time.time()\n        # last epoch duration\n        self.epoch_duration = 0\n        # https://www.metageek.com/training/resources/why-channels-1-6-11.html\n        self.non_overlapping_channels = {1: 0, 6: 0, 11: 0}\n        # observation vectors\n        self._observation = {\n            'aps_histogram': [0.0] * wifi.NumChannels,\n            'sta_histogram': [0.0] * wifi.NumChannels,\n            'peers_histogram': [0.0] * wifi.NumChannels\n        }\n        self._observation_ready = threading.Event()\n        self._epoch_data = {}\n        self._epoch_data_ready = threading.Event()\n        self._reward = RewardFunction()\n\n    def wait_for_epoch_data(self, with_observation=True, timeout=None):\n        # if with_observation:\n        #    self._observation_ready.wait(timeout)\n        #    self._observation_ready.clear()\n        self._epoch_data_ready.wait(timeout)\n        self._epoch_data_ready.clear()\n        return self._epoch_data if with_observation is False else {**self._observation, **self._epoch_data}\n\n    def data(self):\n        return self._epoch_data\n\n    def observe(self, aps, peers):\n        num_aps = len(aps)\n        if num_aps == 0:\n            self.blind_for += 1\n        else:\n            self.blind_for = 0\n\n        bond_unit_scale = self.config['personality']['bond_encounters_factor']\n\n        self.num_peers = len(peers)\n        num_peers = self.num_peers + 1e-10  # avoid division by 0\n\n        self.tot_bond_factor = sum((peer.encounters for peer in peers)) / bond_unit_scale\n        self.avg_bond_factor = self.tot_bond_factor / num_peers\n\n        num_aps = len(aps) + 1e-10\n        num_sta = sum(len(ap['clients']) for ap in aps) + 1e-10\n        aps_per_chan = [0.0] * wifi.NumChannels\n        sta_per_chan = [0.0] * wifi.NumChannels\n        peers_per_chan = [0.0] * wifi.NumChannels\n\n        for ap in aps:\n            ch_idx = ap['channel'] - 1\n            try:\n                aps_per_chan[ch_idx] += 1.0\n                sta_per_chan[ch_idx] += len(ap['clients'])\n            except IndexError:\n                logging.error(\"got data on channel %d, we can store %d channels\" % (ap['channel'], wifi.NumChannels))\n\n        for peer in peers:\n            try:\n                peers_per_chan[peer.last_channel - 1] += 1.0\n            except IndexError:\n                logging.error(\n                    \"got peer data on channel %d, we can store %d channels\" % (peer.last_channel, wifi.NumChannels))\n\n        # normalize\n        aps_per_chan = [e / num_aps for e in aps_per_chan]\n        sta_per_chan = [e / num_sta for e in sta_per_chan]\n        peers_per_chan = [e / num_peers for e in peers_per_chan]\n\n        self._observation = {\n            'aps_histogram': aps_per_chan,\n            'sta_histogram': sta_per_chan,\n            'peers_histogram': peers_per_chan\n        }\n        self._observation_ready.set()\n\n    def track(self, deauth=False, assoc=False, handshake=False, hop=False, sleep=False, miss=False, inc=1):\n        if deauth:\n            self.num_deauths += inc\n            self.did_deauth = True\n            self.any_activity = True\n\n        if assoc:\n            self.num_assocs += inc\n            self.did_associate = True\n            self.any_activity = True\n\n        if miss:\n            self.num_missed += inc\n\n        if hop:\n            self.num_hops += inc\n            # these two are used in order to determine the sleep time in seconds\n            # before switching to a new channel ... if nothing happened so far\n            # during this epoch on the current channel, we will sleep less\n            self.did_deauth = False\n            self.did_associate = False\n\n        if handshake:\n            self.num_shakes += inc\n            self.did_handshakes = True\n\n        if sleep:\n            self.num_slept += inc\n\n    def next(self):\n        if self.any_activity is False and self.did_handshakes is False:\n            self.inactive_for += 1\n            self.active_for = 0\n        else:\n            self.active_for += 1\n            self.inactive_for = 0\n            self.sad_for = 0\n            self.bored_for = 0\n\n        if self.inactive_for >= self.config['personality']['sad_num_epochs']:\n            # sad > bored; cant be sad and bored\n            self.bored_for = 0\n            self.sad_for += 1\n        elif self.inactive_for >= self.config['personality']['bored_num_epochs']:\n            # sad_treshhold > inactive > bored_treshhold; cant be sad and bored\n            self.sad_for = 0\n            self.bored_for += 1\n        else:\n            self.sad_for = 0\n            self.bored_for = 0\n\n        now = time.time()\n        cpu = pwnagotchi.cpu_load()\n        mem = pwnagotchi.mem_usage()\n        temp = pwnagotchi.temperature()\n\n        self.epoch_duration = now - self.epoch_started\n\n        # cache the state of this epoch for other threads to read\n        self._epoch_data = {\n            'duration_secs': self.epoch_duration,\n            'slept_for_secs': self.num_slept,\n            'blind_for_epochs': self.blind_for,\n            'inactive_for_epochs': self.inactive_for,\n            'active_for_epochs': self.active_for,\n            'sad_for_epochs': self.sad_for,\n            'bored_for_epochs': self.bored_for,\n            'missed_interactions': self.num_missed,\n            'num_hops': self.num_hops,\n            'num_peers': self.num_peers,\n            'tot_bond': self.tot_bond_factor,\n            'avg_bond': self.avg_bond_factor,\n            'num_deauths': self.num_deauths,\n            'num_associations': self.num_assocs,\n            'num_handshakes': self.num_shakes,\n            'cpu_load': cpu,\n            'mem_usage': mem,\n            'temperature': temp\n        }\n\n        self._epoch_data['reward'] = self._reward(self.epoch + 1, self._epoch_data)\n        self._epoch_data_ready.set()\n\n        logging.info(\"[epoch %d] duration=%s slept_for=%s blind=%d sad=%d bored=%d inactive=%d active=%d peers=%d tot_bond=%.2f \"\n                     \"avg_bond=%.2f hops=%d missed=%d deauths=%d assocs=%d handshakes=%d cpu=%d%% mem=%d%% \"\n                     \"temperature=%dC reward=%s\" % (\n                         self.epoch,\n                         utils.secs_to_hhmmss(self.epoch_duration),\n                         utils.secs_to_hhmmss(self.num_slept),\n                         self.blind_for,\n                         self.sad_for,\n                         self.bored_for,\n                         self.inactive_for,\n                         self.active_for,\n                         self.num_peers,\n                         self.tot_bond_factor,\n                         self.avg_bond_factor,\n                         self.num_hops,\n                         self.num_missed,\n                         self.num_deauths,\n                         self.num_assocs,\n                         self.num_shakes,\n                         cpu * 100,\n                         mem * 100,\n                         temp,\n                         self._epoch_data['reward']))\n\n        self.epoch += 1\n        self.epoch_started = now\n        self.did_deauth = False\n        self.num_deauths = 0\n        self.num_peers = 0\n        self.tot_bond_factor = 0.0\n        self.avg_bond_factor = 0.0\n        self.did_associate = False\n        self.num_assocs = 0\n        self.num_missed = 0\n        self.did_handshakes = False\n        self.num_shakes = 0\n        self.num_hops = 0\n        self.num_slept = 0\n        self.any_activity = False\n"
  },
  {
    "path": "pwnagotchi/ai/featurizer.py",
    "content": "import numpy as np\n\nimport pwnagotchi.mesh.wifi as wifi\n\nMAX_EPOCH_DURATION = 1024\n\n\ndef describe(extended=False):\n    if not extended:\n        histogram_size = wifi.NumChannels\n    else:\n        # see https://github.com/evilsocket/pwnagotchi/issues/583\n        histogram_size = wifi.NumChannelsExt\n\n    return histogram_size, (1,\n                            # aps per channel\n                            histogram_size +\n                            # clients per channel\n                            histogram_size +\n                            # peers per channel\n                            histogram_size +\n                            # duration\n                            1 +\n                            # inactive\n                            1 +\n                            # active\n                            1 +\n                            # missed\n                            1 +\n                            # hops\n                            1 +\n                            # deauths\n                            1 +\n                            # assocs\n                            1 +\n                            # handshakes\n                            1)\n\n\ndef featurize(state, step):\n    tot_epochs = step + 1e-10\n    tot_interactions = (state['num_deauths'] + state['num_associations']) + 1e-10\n    return np.concatenate((\n        # aps per channel\n        state['aps_histogram'],\n        # clients per channel\n        state['sta_histogram'],\n        # peers per channel\n        state['peers_histogram'],\n        # duration\n        [np.clip(state['duration_secs'] / MAX_EPOCH_DURATION, 0.0, 1.0)],\n        # inactive\n        [state['inactive_for_epochs'] / tot_epochs],\n        # active\n        [state['active_for_epochs'] / tot_epochs],\n        # missed\n        [state['missed_interactions'] / tot_interactions],\n        # hops\n        [state['num_hops'] / wifi.NumChannels],\n        # deauths\n        [state['num_deauths'] / tot_interactions],\n        # assocs\n        [state['num_associations'] / tot_interactions],\n        # handshakes\n        [state['num_handshakes'] / tot_interactions],\n    ))\n"
  },
  {
    "path": "pwnagotchi/ai/gym.py",
    "content": "import logging\nimport gym\nfrom gym import spaces\nimport numpy as np\n\nimport pwnagotchi.ai.featurizer as featurizer\nimport pwnagotchi.ai.reward as reward\nfrom pwnagotchi.ai.parameter import Parameter\n\n\nclass Environment(gym.Env):\n    metadata = {'render.modes': ['human']}\n    params = [\n        Parameter('min_rssi', min_value=-200, max_value=-50),\n        Parameter('ap_ttl', min_value=30, max_value=600),\n        Parameter('sta_ttl', min_value=60, max_value=300),\n\n        Parameter('recon_time', min_value=5, max_value=60),\n        Parameter('max_inactive_scale', min_value=3, max_value=10),\n        Parameter('recon_inactive_multiplier', min_value=1, max_value=3),\n        Parameter('hop_recon_time', min_value=5, max_value=60),\n        Parameter('min_recon_time', min_value=1, max_value=30),\n        Parameter('max_interactions', min_value=1, max_value=25),\n        Parameter('max_misses_for_recon', min_value=3, max_value=10),\n        Parameter('excited_num_epochs', min_value=5, max_value=30),\n        Parameter('bored_num_epochs', min_value=5, max_value=30),\n        Parameter('sad_num_epochs', min_value=5, max_value=30),\n    ]\n\n    def __init__(self, agent, epoch):\n        super(Environment, self).__init__()\n        self._agent = agent\n        self._epoch = epoch\n        self._epoch_num = 0\n        self._last_render = None\n\n        # see https://github.com/evilsocket/pwnagotchi/issues/583\n        self._supported_channels = agent.supported_channels()\n        self._extended_spectrum = any(ch > 140 for ch in self._supported_channels)\n        self._histogram_size, self._observation_shape = featurizer.describe(self._extended_spectrum)\n\n        Environment.params += [\n            Parameter('_channel_%d' % ch, min_value=0, max_value=1, meta=ch + 1) for ch in\n            range(self._histogram_size) if ch + 1 in self._supported_channels\n        ]\n\n        self.last = {\n            'reward': 0.0,\n            'observation': None,\n            'policy': None,\n            'params': {},\n            'state': None,\n            'state_v': None\n        }\n\n        self.action_space = spaces.MultiDiscrete([p.space_size() for p in Environment.params if p.trainable])\n        self.observation_space = spaces.Box(low=0, high=1, shape=self._observation_shape, dtype=np.float32)\n        self.reward_range = reward.range\n\n    @staticmethod\n    def policy_size():\n        return len(list(p for p in Environment.params if p.trainable))\n\n    @staticmethod\n    def policy_to_params(policy):\n        num = len(policy)\n        params = {}\n\n        assert len(Environment.params) == num\n\n        channels = []\n\n        for i in range(num):\n            param = Environment.params[i]\n\n            if '_channel' not in param.name:\n                params[param.name] = param.to_param_value(policy[i])\n            else:\n                has_chan = param.to_param_value(policy[i])\n                # print(\"%s policy:%s bool:%s\" % (param.name, policy[i], has_chan))\n                chan = param.meta\n                if has_chan:\n                    channels.append(chan)\n\n        params['channels'] = channels\n\n        return params\n\n    def _next_epoch(self):\n        logging.debug(\"[ai] waiting for epoch to finish ...\")\n        return self._epoch.wait_for_epoch_data()\n\n    def _apply_policy(self, policy):\n        new_params = Environment.policy_to_params(policy)\n        self.last['policy'] = policy\n        self.last['params'] = new_params\n        self._agent.on_ai_policy(new_params)\n\n    def step(self, policy):\n        # create the parameters from the policy and update\n        # update them in the algorithm\n        self._apply_policy(policy)\n        self._epoch_num += 1\n\n        # wait for the algorithm to run with the new parameters\n        state = self._next_epoch()\n\n        self.last['reward'] = state['reward']\n        self.last['state'] = state\n        self.last['state_v'] = featurizer.featurize(state, self._epoch_num)\n\n        self._agent.on_ai_step()\n\n        return self.last['state_v'], self.last['reward'], not self._agent.is_training(), {}\n\n    def reset(self):\n        # logging.info(\"[ai] resetting environment ...\")\n        self._epoch_num = 0\n        state = self._next_epoch()\n        self.last['state'] = state\n        self.last['state_v'] = featurizer.featurize(state, 1)\n        return self.last['state_v']\n\n    def _render_histogram(self, hist):\n        for ch in range(self._histogram_size):\n            if hist[ch]:\n                logging.info(\"      CH %d: %s\" % (ch + 1, hist[ch]))\n\n    def render(self, mode='human', close=False, force=False):\n        # when using a vectorialized environment, render gets called twice\n        # avoid rendering the same data\n        if self._last_render == self._epoch_num:\n            return\n\n        if not self._agent.is_training() and not force:\n            return\n\n        self._last_render = self._epoch_num\n\n        logging.info(\"[ai] --- training epoch %d/%d ---\" % (self._epoch_num, self._agent.training_epochs()))\n        logging.info(\"[ai] REWARD: %f\" % self.last['reward'])\n\n        logging.debug(\"[ai] policy: %s\" % ', '.join(\"%s:%s\" % (name, value) for name, value in self.last['params'].items()))\n\n        logging.info(\"[ai] observation:\")\n        for name, value in self.last['state'].items():\n            if 'histogram' in name:\n                logging.info(\"    %s\" % name.replace('_histogram', ''))\n                self._render_histogram(value)\n"
  },
  {
    "path": "pwnagotchi/ai/parameter.py",
    "content": "from gym import spaces\n\n\nclass Parameter(object):\n    def __init__(self, name, value=0.0, min_value=0, max_value=2, meta=None, trainable=True):\n        self.name = name\n        self.trainable = trainable\n        self.meta = meta\n        self.value = value\n        self.min_value = min_value\n        self.max_value = max_value + 1\n\n        # gym.space.Discrete is within [0, 1, 2, ..., n-1]\n        if self.min_value < 0:\n            self.scale_factor = abs(self.min_value)\n        elif self.min_value > 0:\n            self.scale_factor = -self.min_value\n        else:\n            self.scale_factor = 0\n\n    def space_size(self):\n        return self.max_value + self.scale_factor\n\n    def space(self):\n        return spaces.Discrete(self.max_value + self.scale_factor)\n\n    def to_param_value(self, policy_v):\n        self.value = policy_v - self.scale_factor\n        assert self.min_value <= self.value <= self.max_value\n        return int(self.value)\n"
  },
  {
    "path": "pwnagotchi/ai/reward.py",
    "content": "import pwnagotchi.mesh.wifi as wifi\n\nrange = (-.7, 1.02)\nfuck_zero = 1e-20\n\n\nclass RewardFunction(object):\n    def __call__(self, epoch_n, state):\n        tot_epochs = epoch_n + fuck_zero\n        tot_interactions = max(state['num_deauths'] + state['num_associations'], state['num_handshakes']) + fuck_zero\n        tot_channels = wifi.NumChannels\n\n        h = state['num_handshakes'] / tot_interactions\n        a = .2 * (state['active_for_epochs'] / tot_epochs)\n        c = .1 * (state['num_hops'] / tot_channels)\n\n        b = -.3 * (state['blind_for_epochs'] / tot_epochs)\n        m = -.3 * (state['missed_interactions'] / tot_interactions)\n        i = -.2 * (state['inactive_for_epochs'] / tot_epochs)\n\n        # include emotions if state >= 5 epochs\n        _sad = state['sad_for_epochs'] if state['sad_for_epochs'] >= 5 else 0\n        _bored = state['bored_for_epochs'] if state['bored_for_epochs'] >= 5 else 0\n        s = -.2 * (_sad / tot_epochs)\n        l = -.1 * (_bored / tot_epochs)\n\n        return h + a + c + b + i + m + s + l\n"
  },
  {
    "path": "pwnagotchi/ai/train.py",
    "content": "import _thread\nimport threading\nimport time\nimport random\nimport os\nimport json\nimport logging\n\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi.ai as ai\n\n\nclass Stats(object):\n    def __init__(self, path, events_receiver):\n        self._lock = threading.Lock()\n        self._receiver = events_receiver\n\n        self.path = path\n        self.born_at = time.time()\n        # total epochs lived (trained + just eval)\n        self.epochs_lived = 0\n        # total training epochs\n        self.epochs_trained = 0\n\n        self.worst_reward = 0.0\n        self.best_reward = 0.0\n\n        self.load()\n\n    def on_epoch(self, data, training):\n        best_r = False\n        worst_r = False\n        with self._lock:\n            reward = data['reward']\n            if reward < self.worst_reward:\n                self.worst_reward = reward\n                worst_r = True\n\n            elif reward > self.best_reward:\n                best_r = True\n                self.best_reward = reward\n\n            self.epochs_lived += 1\n            if training:\n                self.epochs_trained += 1\n\n        self.save()\n\n        if best_r:\n            self._receiver.on_ai_best_reward(reward)\n        elif worst_r:\n            self._receiver.on_ai_worst_reward(reward)\n\n    def load(self):\n        with self._lock:\n            if os.path.exists(self.path) and os.path.getsize(self.path) > 0:\n                logging.info(\"[ai] loading %s\" % self.path)\n                with open(self.path, 'rt') as fp:\n                    obj = json.load(fp)\n\n                self.born_at = obj['born_at']\n                self.epochs_lived, self.epochs_trained = obj['epochs_lived'], obj['epochs_trained']\n                self.best_reward, self.worst_reward = obj['rewards']['best'], obj['rewards']['worst']\n\n    def save(self):\n        with self._lock:\n            logging.info(\"[ai] saving %s\" % self.path)\n\n            data = json.dumps({\n                'born_at': self.born_at,\n                'epochs_lived': self.epochs_lived,\n                'epochs_trained': self.epochs_trained,\n                'rewards': {\n                    'best': self.best_reward,\n                    'worst': self.worst_reward\n                }\n            })\n\n            temp = \"%s.tmp\" % self.path\n            with open(temp, 'wt') as fp:\n                fp.write(data)\n\n            os.replace(temp, self.path)\n\n\nclass AsyncTrainer(object):\n    def __init__(self, config):\n        self._config = config\n        self._model = None\n        self._is_training = False\n        self._training_epochs = 0\n        self._nn_path = self._config['ai']['path']\n        self._stats = Stats(\"%s.json\" % os.path.splitext(self._nn_path)[0], self)\n\n    def set_training(self, training, for_epochs=0):\n        self._is_training = training\n        self._training_epochs = for_epochs\n\n        if training:\n            plugins.on('ai_training_start', self, for_epochs)\n        else:\n            plugins.on('ai_training_end', self)\n\n    def is_training(self):\n        return self._is_training\n\n    def training_epochs(self):\n        return self._training_epochs\n\n    def start_ai(self):\n        _thread.start_new_thread(self._ai_worker, ())\n\n    def _save_ai(self):\n        logging.info(\"[ai] saving model to %s ...\" % self._nn_path)\n        temp = \"%s.tmp\" % self._nn_path\n        self._model.save(temp)\n        os.replace(temp, self._nn_path)\n\n    def on_ai_step(self):\n        self._model.env.render()\n\n        if self._is_training:\n            self._save_ai()\n\n        self._stats.on_epoch(self._epoch.data(), self._is_training)\n\n    def on_ai_training_step(self, _locals, _globals):\n        self._model.env.render()\n        plugins.on('ai_training_step', self, _locals, _globals)\n\n    def on_ai_policy(self, new_params):\n        plugins.on('ai_policy', self, new_params)\n        logging.info(\"[ai] setting new policy:\")\n        for name, value in new_params.items():\n            if name in self._config['personality']:\n                curr_value = self._config['personality'][name]\n                if curr_value != value:\n                    logging.info(\"[ai] ! %s: %s -> %s\" % (name, curr_value, value))\n                    self._config['personality'][name] = value\n            else:\n                logging.error(\"[ai] param %s not in personality configuration!\" % name)\n\n        self.run('set wifi.ap.ttl %d' % self._config['personality']['ap_ttl'])\n        self.run('set wifi.sta.ttl %d' % self._config['personality']['sta_ttl'])\n        self.run('set wifi.rssi.min %d' % self._config['personality']['min_rssi'])\n\n    def on_ai_ready(self):\n        self._view.on_ai_ready()\n        plugins.on('ai_ready', self)\n\n    def on_ai_best_reward(self, r):\n        logging.info(\"[ai] best reward so far: %s\" % r)\n        self._view.on_motivated(r)\n        plugins.on('ai_best_reward', self, r)\n\n    def on_ai_worst_reward(self, r):\n        logging.info(\"[ai] worst reward so far: %s\" % r)\n        self._view.on_demotivated(r)\n        plugins.on('ai_worst_reward', self, r)\n\n    def _ai_worker(self):\n        self._model = ai.load(self._config, self, self._epoch)\n\n        if self._model:\n            self.on_ai_ready()\n\n            epochs_per_episode = self._config['ai']['epochs_per_episode']\n\n            obs = None\n            while True:\n                self._model.env.render()\n                # enter in training mode?\n                if random.random() > self._config['ai']['laziness']:\n                    logging.info(\"[ai] learning for %d epochs ...\" % epochs_per_episode)\n                    try:\n                        self.set_training(True, epochs_per_episode)\n                        self._model.learn(total_timesteps=epochs_per_episode, callback=self.on_ai_training_step)\n                    except Exception as e:\n                        logging.exception(\"[ai] error while training (%s)\", e)\n                    finally:\n                        self.set_training(False)\n                        obs = self._model.env.reset()\n                # init the first time\n                elif obs is None:\n                    obs = self._model.env.reset()\n\n                # run the inference\n                action, _ = self._model.predict(obs)\n                obs, _, _, _ = self._model.env.step(action)\n"
  },
  {
    "path": "pwnagotchi/ai/utils.py",
    "content": "import numpy as np\n\n\ndef normalize(v, min_v, max_v):\n    return (v - min_v) / (max_v - min_v)\n\n\ndef as_batches(x, y, batch_size, shuffle=True):\n    x_size = len(x)\n    assert x_size == len(y)\n\n    indices = np.random.permutation(x_size) if shuffle else None\n\n    for offset in range(0, x_size - batch_size + 1, batch_size):\n        excerpt = indices[offset:offset + batch_size] if shuffle else slice(offset, offset + batch_size)\n        yield x[excerpt], y[excerpt]\n"
  },
  {
    "path": "pwnagotchi/automata.py",
    "content": "import logging\n\nimport pwnagotchi.plugins as plugins\nfrom pwnagotchi.ai.epoch import Epoch\n\n\n# basic mood system\nclass Automata(object):\n    def __init__(self, config, view):\n        self._config = config\n        self._view = view\n        self._epoch = Epoch(config)\n\n    def _on_miss(self, who):\n        logging.info(\"it looks like %s is not in range anymore :/\", who)\n        self._epoch.track(miss=True)\n        self._view.on_miss(who)\n\n    def _on_error(self, who, e):\n        # when we're trying to associate or deauth something that is not in range anymore\n        # (if we are moving), we get the following error from bettercap:\n        # error 400: 50:c7:bf:2e:d3:37 is an unknown BSSID or it is in the association skip list.\n        if 'is an unknown BSSID' in str(e):\n            self._on_miss(who)\n        else:\n            logging.error(e)\n\n    def set_starting(self):\n        self._view.on_starting()\n\n    def set_ready(self):\n        plugins.on('ready', self)\n\n    def in_good_mood(self):\n        return self._has_support_network_for(1.0)\n\n    def _has_support_network_for(self, factor):\n        bond_factor = self._config['personality']['bond_encounters_factor']\n        total_encounters = sum(peer.encounters for _, peer in self._peers.items())\n        support_factor = total_encounters / bond_factor\n        return support_factor >= factor\n\n    # triggered when it's a sad/bad day but you have good friends around ^_^\n    def set_grateful(self):\n        self._view.on_grateful()\n        plugins.on('grateful', self)\n\n    def set_lonely(self):\n        if not self._has_support_network_for(1.0):\n            logging.info(\"unit is lonely\")\n            self._view.on_lonely()\n            plugins.on('lonely', self)\n        else:\n            logging.info(\"unit is grateful instead of lonely\")\n            self.set_grateful()\n\n    def set_bored(self):\n        factor = self._epoch.inactive_for / self._config['personality']['bored_num_epochs']\n        if not self._has_support_network_for(factor):\n            logging.warning(\"%d epochs with no activity -> bored\", self._epoch.inactive_for)\n            self._view.on_bored()\n            plugins.on('bored', self)\n        else:\n            logging.info(\"unit is grateful instead of bored\")\n            self.set_grateful()\n\n    def set_sad(self):\n        factor = self._epoch.inactive_for / self._config['personality']['sad_num_epochs']\n        if not self._has_support_network_for(factor):\n            logging.warning(\"%d epochs with no activity -> sad\", self._epoch.inactive_for)\n            self._view.on_sad()\n            plugins.on('sad', self)\n        else:\n            logging.info(\"unit is grateful instead of sad\")\n            self.set_grateful()\n\n    def set_angry(self, factor):\n        if not self._has_support_network_for(factor):\n            logging.warning(\"%d epochs with no activity -> angry\", self._epoch.inactive_for)\n            self._view.on_angry()\n            plugins.on('angry', self)\n        else:\n            logging.info(\"unit is grateful instead of angry\")\n            self.set_grateful()\n\n    def set_excited(self):\n        logging.warning(\"%d epochs with activity -> excited\", self._epoch.active_for)\n        self._view.on_excited()\n        plugins.on('excited', self)\n\n    def set_rebooting(self):\n        self._view.on_rebooting()\n        plugins.on('rebooting', self)\n\n    def wait_for(self, t, sleeping=True):\n        plugins.on('sleep' if sleeping else 'wait', self, t)\n        self._view.wait(t, sleeping)\n        self._epoch.track(sleep=True, inc=t)\n\n    def is_stale(self):\n        return self._epoch.num_missed > self._config['personality']['max_misses_for_recon']\n\n    def any_activity(self):\n        return self._epoch.any_activity\n\n    def next_epoch(self):\n        logging.debug(\"agent.next_epoch()\")\n\n        was_stale = self.is_stale()\n        did_miss = self._epoch.num_missed\n\n        self._epoch.next()\n\n        # after X misses during an epoch, set the status to lonely or angry\n        if was_stale:\n            factor = did_miss / self._config['personality']['max_misses_for_recon']\n            if factor >= 2.0:\n                self.set_angry(factor)\n            else:\n                logging.warning(\"agent missed %d interactions -> lonely\", did_miss)\n                self.set_lonely()\n        # after X times being bored, the status is set to sad or angry\n        elif self._epoch.sad_for:\n            factor = self._epoch.inactive_for / self._config['personality']['sad_num_epochs']\n            if factor >= 2.0:\n                self.set_angry(factor)\n            else:\n                self.set_sad()\n        # after X times being inactive, the status is set to bored\n        elif self._epoch.bored_for:\n            self.set_bored()\n        # after X times being active, the status is set to happy / excited\n        elif self._epoch.active_for >= self._config['personality']['excited_num_epochs']:\n            self.set_excited()\n        elif self._epoch.active_for >= 5 and self._has_support_network_for(5.0):\n            self.set_grateful()\n\n        plugins.on('epoch', self, self._epoch.epoch - 1, self._epoch.data())\n\n        if self._epoch.blind_for >= self._config['main']['mon_max_blind_epochs']:\n            logging.critical(\"%d epochs without visible access points -> rebooting ...\", self._epoch.blind_for)\n            self._reboot()\n            self._epoch.blind_for = 0\n"
  },
  {
    "path": "pwnagotchi/bettercap.py",
    "content": "import json\nimport logging\nimport requests\nimport websockets\n\nfrom requests.auth import HTTPBasicAuth\n\n\ndef decode(r, verbose_errors=True):\n    try:\n        return r.json()\n    except Exception as e:\n        if r.status_code == 200:\n            logging.error(\"error while decoding json: error='%s' resp='%s'\" % (e, r.text))\n        else:\n            err = \"error %d: %s\" % (r.status_code, r.text.strip())\n            if verbose_errors:\n                logging.info(err)\n            raise Exception(err)\n        return r.text\n\n\nclass Client(object):\n    def __init__(self, hostname='localhost', scheme='http', port=8081, username='user', password='pass'):\n        self.hostname = hostname\n        self.scheme = scheme\n        self.port = port\n        self.username = username\n        self.password = password\n        self.url = \"%s://%s:%d/api\" % (scheme, hostname, port)\n        self.websocket = \"ws://%s:%s@%s:%d/api\" % (username, password, hostname, port)\n        self.auth = HTTPBasicAuth(username, password)\n\n    def session(self):\n        r = requests.get(\"%s/session\" % self.url, auth=self.auth)\n        return decode(r)\n\n    async def start_websocket(self, consumer):\n        s = \"%s/events\" % self.websocket\n        while True:\n            try:\n                async with websockets.connect(s, ping_interval=60, ping_timeout=90) as ws:\n                    async for msg in ws:\n                        try:\n                            await consumer(msg)\n                        except Exception as ex:\n                            logging.debug(\"Error while parsing event (%s)\", ex)\n            except websockets.exceptions.ConnectionClosedError:\n                logging.debug(\"Lost websocket connection. Reconnecting...\")\n            except websockets.exceptions.WebSocketException as wex:\n                logging.debug(\"Websocket exception (%s)\", wex)\n\n    def run(self, command, verbose_errors=True):\n        r = requests.post(\"%s/session\" % self.url, auth=self.auth, json={'cmd': command})\n        return decode(r, verbose_errors=verbose_errors)\n"
  },
  {
    "path": "pwnagotchi/defaults.toml",
    "content": "main.name = \"\"\nmain.lang = \"en\"\nmain.confd = \"/etc/pwnagotchi/conf.d/\"\nmain.custom_plugins = \"\"\nmain.custom_plugin_repos = [\n  \"https://github.com/evilsocket/pwnagotchi-plugins-contrib/archive/master.zip\"\n]\nmain.iface = \"mon0\"\nmain.mon_start_cmd = \"/usr/bin/monstart\"\nmain.mon_stop_cmd = \"/usr/bin/monstop\"\nmain.mon_max_blind_epochs = 50\nmain.no_restart = false\nmain.whitelist = [\n  \"EXAMPLE_NETWORK\",\n  \"ANOTHER_EXAMPLE_NETWORK\",\n  \"fo:od:ba:be:fo:od\",\n  \"fo:od:ba\"\n]\nmain.filter = \"\"\n\nmain.plugins.grid.enabled = true\nmain.plugins.grid.report = false\nmain.plugins.grid.exclude = [\n  \"YourHomeNetworkHere\"\n]\n\nmain.plugins.auto-update.enabled = true\nmain.plugins.auto-update.install = true\nmain.plugins.auto-update.interval = 1\n\nmain.plugins.net-pos.enabled = false\nmain.plugins.net-pos.api_key = \"test\"\n\nmain.plugins.gps.enabled = false\nmain.plugins.gps.speed = 19200\nmain.plugins.gps.device = \"/dev/ttyUSB0\"\n\nmain.plugins.webgpsmap.enabled = false\n\nmain.plugins.onlinehashcrack.enabled = false\nmain.plugins.onlinehashcrack.email = \"\"\nmain.plugins.onlinehashcrack.dashboard = \"\"\nmain.plugins.onlinehashcrack.single_files = false\nmain.plugins.onlinehashcrack.whitelist = []\n\nmain.plugins.wpa-sec.enabled = false\nmain.plugins.wpa-sec.api_key = \"\"\nmain.plugins.wpa-sec.api_url = \"https://wpa-sec.stanev.org\"\nmain.plugins.wpa-sec.download_results = false\nmain.plugins.wpa-sec.whitelist = []\n\nmain.plugins.wigle.enabled = false\nmain.plugins.wigle.api_key = \"\"\nmain.plugins.wigle.whitelist = []\nmain.plugins.wigle.donate = true\n\nmain.plugins.bt-tether.enabled = false\n\nmain.plugins.bt-tether.devices.android-phone.enabled = false\nmain.plugins.bt-tether.devices.android-phone.search_order = 1\nmain.plugins.bt-tether.devices.android-phone.mac = \"\"\nmain.plugins.bt-tether.devices.android-phone.ip = \"192.168.44.44\"\nmain.plugins.bt-tether.devices.android-phone.netmask = 24\nmain.plugins.bt-tether.devices.android-phone.interval = 1\nmain.plugins.bt-tether.devices.android-phone.scantime = 10\nmain.plugins.bt-tether.devices.android-phone.max_tries = 10\nmain.plugins.bt-tether.devices.android-phone.share_internet = false\nmain.plugins.bt-tether.devices.android-phone.priority = 1\n\nmain.plugins.bt-tether.devices.ios-phone.enabled = false\nmain.plugins.bt-tether.devices.ios-phone.search_order = 2\nmain.plugins.bt-tether.devices.ios-phone.mac = \"\"\nmain.plugins.bt-tether.devices.ios-phone.ip = \"172.20.10.6\"\nmain.plugins.bt-tether.devices.ios-phone.netmask = 24\nmain.plugins.bt-tether.devices.ios-phone.interval = 5\nmain.plugins.bt-tether.devices.ios-phone.scantime = 20\nmain.plugins.bt-tether.devices.ios-phone.max_tries = 0\nmain.plugins.bt-tether.devices.ios-phone.share_internet = false\nmain.plugins.bt-tether.devices.ios-phone.priority = 999\n\nmain.plugins.memtemp.enabled = false\nmain.plugins.memtemp.scale = \"celsius\"\nmain.plugins.memtemp.orientation = \"horizontal\"\n\nmain.plugins.paw-gps.enabled = false\nmain.plugins.paw-gps.ip = \"192.168.44.1:8080\"\n\nmain.plugins.ups_lite.enabled = false\nmain.plugins.ups_lite.shutdown = 2\n\nmain.plugins.gpio_buttons.enabled = false\n\nmain.plugins.led.enabled = true\nmain.plugins.led.led = 0\nmain.plugins.led.delay = 200\nmain.plugins.led.patterns.loaded = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.updating = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.unread_inbox = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.ready = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.ai_ready = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.ai_training_start = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.ai_best_reward = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.ai_worst_reward = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.bored = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.sad = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.excited = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.lonely = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.rebooting = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.wait = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.sleep = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.wifi_update = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.association = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.deauthentication = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.handshake = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.epoch = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.peer_detected = \"oo  oo  oo oo  oo  oo  oo\"\nmain.plugins.led.patterns.peer_lost = \"oo  oo  oo oo  oo  oo  oo\"\n\nmain.plugins.logtail.enabled = false\nmain.plugins.logtail.max-lines = 10000\n\nmain.plugins.session-stats.enabled = true\nmain.plugins.session-stats.save_directory = \"/var/tmp/pwnagotchi/sessions/\"\n\nmain.log.path = \"/var/log/pwnagotchi.log\"\nmain.log.rotation.enabled = true\nmain.log.rotation.size = \"10M\"\n\nai.enabled = true\nai.path = \"/root/brain.nn\"\nai.laziness = 0.1\nai.epochs_per_episode = 50\n\nai.params.gamma = 0.99\nai.params.n_steps = 1\nai.params.vf_coef = 0.25\nai.params.ent_coef = 0.01\nai.params.max_grad_norm = 0.5\nai.params.learning_rate = 0.001\nai.params.alpha = 0.99\nai.params.epsilon = 0.00001\nai.params.verbose = 1\nai.params.lr_schedule = \"constant\"\n\npersonality.advertise = true\npersonality.deauth = true\npersonality.associate = true\npersonality.channels = []\npersonality.min_rssi = -200\npersonality.ap_ttl = 120\npersonality.sta_ttl = 300\npersonality.recon_time = 30\npersonality.max_inactive_scale = 2\npersonality.recon_inactive_multiplier = 2\npersonality.hop_recon_time = 10\npersonality.min_recon_time = 5\npersonality.max_interactions = 3\npersonality.max_misses_for_recon = 5\npersonality.excited_num_epochs = 10\npersonality.bored_num_epochs = 15\npersonality.sad_num_epochs = 25\npersonality.bond_encounters_factor = 20000\n\nui.fps = 0.0\nui.font.name = \"DejaVuSansMono\" # for japanese: fonts-japanese-gothic\nui.font.size_offset = 0 # will be added to the font size\n\nui.faces.look_r = \"( ⚆_⚆)\"\nui.faces.look_l = \"(☉_☉ )\"\nui.faces.look_r_happy = \"( ◕‿◕)\"\nui.faces.look_l_happy = \"(◕‿◕ )\"\nui.faces.sleep = \"(⇀‿‿↼)\"\nui.faces.sleep2 = \"(≖‿‿≖)\"\nui.faces.awake = \"(◕‿‿◕)\"\nui.faces.bored = \"(-__-)\"\nui.faces.intense = \"(°▃▃°)\"\nui.faces.cool = \"(⌐■_■)\"\nui.faces.happy = \"(•‿‿•)\"\nui.faces.excited = \"(ᵔ◡◡ᵔ)\"\nui.faces.grateful = \"(^‿‿^)\"\nui.faces.motivated = \"(☼‿‿☼)\"\nui.faces.demotivated = \"(≖__≖)\"\nui.faces.smart = \"(✜‿‿✜)\"\nui.faces.lonely = \"(ب__ب)\"\nui.faces.sad = \"(╥☁╥ )\"\nui.faces.angry = \"(-_-')\"\nui.faces.friend = \"(♥‿‿♥)\"\nui.faces.broken = \"(☓‿‿☓)\"\nui.faces.debug = \"(#__#)\"\nui.faces.upload = \"(1__0)\"\nui.faces.upload1 = \"(1__1)\"\nui.faces.upload2 = \"(0__1)\"\n\nui.web.enabled = true\nui.web.address = \"0.0.0.0\"\nui.web.username = \"changeme\"\nui.web.password = \"changeme\"\nui.web.origin = \"\"\nui.web.port = 8080\nui.web.on_frame = \"\"\n\nui.display.enabled = true\nui.display.rotation = 180\nui.display.type = \"waveshare_2\"\nui.display.color = \"black\"\n\nbettercap.scheme = \"http\"\nbettercap.hostname = \"localhost\"\nbettercap.port = 8081\nbettercap.username = \"pwnagotchi\"\nbettercap.password = \"pwnagotchi\"\nbettercap.handshakes = \"/root/handshakes\"\nbettercap.silence = [\n  \"ble.device.new\",\n  \"ble.device.lost\",\n  \"ble.device.disconnected\",\n  \"ble.device.connected\",\n  \"ble.device.service.discovered\",\n  \"ble.device.characteristic.discovered\",\n  \"wifi.client.new\",\n  \"wifi.client.lost\",\n  \"wifi.client.probe\",\n  \"wifi.ap.new\",\n  \"wifi.ap.lost\",\n  \"mod.started\"\n]\n\nfs.memory.enabled = false\nfs.memory.mounts.log.enabled = false\nfs.memory.mounts.log.mount = \"/var/log\"\nfs.memory.mounts.log.size = \"50M\"\nfs.memory.mounts.log.sync = 60\nfs.memory.mounts.log.zram = true\nfs.memory.mounts.log.rsync = true\n\nfs.memory.mounts.data.enabled = false\nfs.memory.mounts.data.mount = \"/var/tmp/pwnagotchi\"\nfs.memory.mounts.data.size = \"10M\"\nfs.memory.mounts.data.sync = 3600\nfs.memory.mounts.data.zram = false\nfs.memory.mounts.data.rsync = true\n"
  },
  {
    "path": "pwnagotchi/fs/__init__.py",
    "content": "import os\nimport re\nimport tempfile\nimport contextlib\nimport shutil\nimport _thread\nimport logging\n\nfrom time import sleep\nfrom distutils.dir_util import copy_tree\n\nmounts = list()\n\n\n@contextlib.contextmanager\ndef ensure_write(filename, mode='w'):\n    path = os.path.dirname(filename)\n    fd, tmp = tempfile.mkstemp(dir=path)\n\n    with os.fdopen(fd, mode) as f:\n        yield f\n        f.flush()\n        os.fsync(f.fileno())\n\n    os.replace(tmp, filename)\n\n\ndef size_of(path):\n    \"\"\"\n    Calculate the sum of all the files in path\n    \"\"\"\n    total = 0\n    for root, _, files in os.walk(path):\n        for f in files:\n            total += os.path.getsize(os.path.join(root, f))\n    return total\n\n\ndef is_mountpoint(path):\n    \"\"\"\n    Checks if path is mountpoint\n    \"\"\"\n    return os.system(f\"mountpoint -q {path}\") == 0\n\n\ndef setup_mounts(config):\n    \"\"\"\n    Sets up all the configured mountpoints\n    \"\"\"\n    global mounts\n    fs_cfg = config['fs']['memory']\n    if not fs_cfg['enabled']:\n        return\n\n    for name, options in fs_cfg['mounts'].items():\n        if not options['enabled']:\n            continue\n        logging.debug(\"[FS] Trying to setup mount %s (%s)\", name, options['mount'])\n        size,unit = re.match(r\"(\\d+)([a-zA-Z]+)\", options['size']).groups()\n        target = os.path.join('/run/pwnagotchi/disk/', os.path.basename(options['mount']))\n\n        is_mounted = is_mountpoint(target)\n        logging.debug(\"[FS] %s is %s mounted\", options['mount'],\n                      \"already\" if is_mounted else \"not yet\")\n\n        m = MemoryFS(\n            options['mount'],\n            target,\n            size=options['size'],\n            zram=options['zram'],\n            zram_disk_size=f\"{int(size)*2}{unit}\",\n            rsync=options['rsync'])\n\n        if not is_mounted:\n            if not m.mount():\n                logging.debug(f\"Error while mounting {m.mountpoint}\")\n                continue\n\n            if not m.sync(to_ram=True):\n                logging.debug(f\"Error while syncing to {m.mountpoint}\")\n                m.umount()\n                continue\n\n        interval = int(options['sync'])\n        if interval:\n            logging.debug(\"[FS] Starting thread to sync %s (interval: %d)\",\n                        options['mount'], interval)\n            _thread.start_new_thread(m.daemonize, (interval,))\n        else:\n            logging.debug(\"[FS] Not syncing %s, because interval is 0\",\n            options['mount'])\n\n        mounts.append(m)\n\n\nclass MemoryFS:\n    @staticmethod\n    def zram_install():\n        if not os.path.exists(\"/sys/class/zram-control\"):\n            logging.debug(\"[FS] Installing zram\")\n            return os.system(\"modprobe zram\") == 0\n        return True\n\n\n    @staticmethod\n    def zram_dev():\n        logging.debug(\"[FS] Adding zram device\")\n        return open(\"/sys/class/zram-control/hot_add\", \"rt\").read().strip(\"\\n\")\n\n\n    def __init__(self, mount, disk, size=\"40M\",\n                 zram=True, zram_alg=\"lz4\", zram_disk_size=\"100M\",\n                 zram_fs_type=\"ext4\", rsync=True):\n        self.mountpoint = mount\n        self.disk = disk\n        self.size = size\n        self.zram = zram\n        self.zram_alg = zram_alg\n        self.zram_disk_size = zram_disk_size\n        self.zram_fs_type = zram_fs_type\n        self.zdev = None\n        self.rsync = True\n        self._setup()\n\n\n    def _setup(self):\n        if self.zram and MemoryFS.zram_install():\n            # setup zram\n            self.zdev = MemoryFS.zram_dev()\n            open(f\"/sys/block/zram{self.zdev}/comp_algorithm\", \"wt\").write(self.zram_alg)\n            open(f\"/sys/block/zram{self.zdev}/disksize\", \"wt\").write(self.zram_disk_size)\n            open(f\"/sys/block/zram{self.zdev}/mem_limit\", \"wt\").write(self.size)\n            logging.debug(\"[FS] Creating fs (type: %s)\", self.zram_fs_type)\n            os.system(f\"mke2fs -t {self.zram_fs_type} /dev/zram{self.zdev} >/dev/null 2>&1\")\n\n        # ensure mountpoints exist\n        if not os.path.exists(self.disk):\n            logging.debug(\"[FS] Creating %s\", self.disk)\n            os.makedirs(self.disk)\n\n        if not os.path.exists(self.mountpoint):\n            logging.debug(\"[FS] Creating %s\", self.mountpoint)\n            os.makedirs(self.mountpoint)\n\n\n    def daemonize(self, interval=60):\n        logging.debug(\"[FS] Daemonized...\")\n        while True:\n            self.sync()\n            sleep(interval)\n\n\n    def sync(self, to_ram=False):\n        source, dest = (self.disk, self.mountpoint) if to_ram else (self.mountpoint, self.disk)\n        needed, actually_free = size_of(source), shutil.disk_usage(dest)[2]\n        if actually_free >= needed:\n            logging.debug(\"[FS] Syncing %s -> %s\", source,dest)\n            if self.rsync:\n                os.system(f\"rsync -aXv --inplace --no-whole-file --delete-after {source}/ {dest}/ >/dev/null 2>&1\")\n            else:\n                copy_tree(source, dest, preserve_symlinks=True)\n            os.system(\"sync\")\n            return True\n        return False\n\n\n    def mount(self):\n        if os.system(f\"mount --bind {self.mountpoint} {self.disk}\"):\n            return False\n\n        if os.system(f\"mount --make-private {self.disk}\"):\n            return False\n\n        if self.zram and self.zdev is not None:\n            if os.system(f\"mount -t {self.zram_fs_type} -o nosuid,noexec,nodev,user=pwnagotchi /dev/zram{self.zdev} {self.mountpoint}/\"):\n                return False\n        else:\n            if os.system(f\"mount -t tmpfs -o nosuid,noexec,nodev,mode=0755,size={self.size} pwnagotchi {self.mountpoint}/\"):\n                return False\n\n        return True\n\n\n    def umount(self):\n        if os.system(f\"umount -l {self.mountpoint}\"):\n            return False\n\n        if os.system(f\"umount -l {self.disk}\"):\n            return False\n        return True\n"
  },
  {
    "path": "pwnagotchi/grid.py",
    "content": "import subprocess\nimport socket\nimport requests\nimport json\nimport logging\n\nimport pwnagotchi\n\n# pwngrid-peer is running on port 8666\nAPI_ADDRESS = \"http://127.0.0.1:8666/api/v1\"\n\n\ndef is_connected():\n    try:\n        # check DNS\n        host = socket.gethostbyname('api.pwnagotchi.ai')\n        if host:\n            # check connectivity itself\n            socket.create_connection((host, 443), timeout=30)\n            return True\n    except:\n        pass\n    return False\n\n\ndef call(path, obj=None):\n    url = '%s%s' % (API_ADDRESS, path)\n    if obj is None:\n        r = requests.get(url, headers=None, timeout=(30.0, 60.0))\n    elif isinstance(obj, dict):\n        r = requests.post(url, headers=None, json=obj, timeout=(30.0, 60.0))\n    else:\n        r = requests.post(url, headers=None, data=obj, timeout=(30.0, 60.0))\n\n    if r.status_code != 200:\n        raise Exception(\"(status %d) %s\" % (r.status_code, r.text))\n    return r.json()\n\n\ndef advertise(enabled=True):\n    return call(\"/mesh/%s\" % 'true' if enabled else 'false')\n\n\ndef set_advertisement_data(data):\n    return call(\"/mesh/data\", obj=data)\n\n\ndef get_advertisement_data():\n    return call(\"/mesh/data\")\n\n\ndef memory():\n    return call(\"/mesh/memory\")\n\n\ndef peers():\n    return call(\"/mesh/peers\")\n\n\ndef closest_peer():\n    all = peers()\n    return all[0] if len(all) else None\n\n\ndef update_data(last_session):\n    brain = {}\n    try:\n        with open('/root/brain.json') as fp:\n            brain = json.load(fp)\n    except:\n        pass\n\n    data = {\n        'session': {\n            'duration': last_session.duration,\n            'epochs': last_session.epochs,\n            'train_epochs': last_session.train_epochs,\n            'avg_reward': last_session.avg_reward,\n            'min_reward': last_session.min_reward,\n            'max_reward': last_session.max_reward,\n            'deauthed': last_session.deauthed,\n            'associated': last_session.associated,\n            'handshakes': last_session.handshakes,\n            'peers': last_session.peers,\n        },\n        'uname': subprocess.getoutput(\"uname -a\"),\n        'brain': brain,\n        'version': pwnagotchi.__version__\n    }\n\n    logging.debug(\"updating grid data: %s\" % data)\n\n    call(\"/data\", data)\n\n\ndef report_ap(essid, bssid):\n    try:\n        call(\"/report/ap\", {\n            'essid': essid,\n            'bssid': bssid,\n        })\n        return True\n    except Exception as e:\n        logging.exception(\"error while reporting ap %s(%s)\" % (essid, bssid))\n\n    return False\n\n\ndef inbox(page=1, with_pager=False):\n    obj = call(\"/inbox?p=%d\" % page)\n    return obj[\"messages\"] if not with_pager else obj\n\n\ndef inbox_message(id):\n    return call(\"/inbox/%d\" % int(id))\n\n\ndef mark_message(id, mark):\n    return call(\"/inbox/%d/%s\" % (int(id), str(mark)))\n\n\ndef send_message(to, message):\n    return call(\"/unit/%s/inbox\" % to, message.encode('utf-8'))\n"
  },
  {
    "path": "pwnagotchi/identity.py",
    "content": "from Crypto.Signature import PKCS1_PSS\nfrom Crypto.PublicKey import RSA\nimport Crypto.Hash.SHA256 as SHA256\nimport base64\nimport hashlib\nimport os\nimport logging\n\nDefaultPath = \"/etc/pwnagotchi/\"\n\n\nclass KeyPair(object):\n    def __init__(self, path=DefaultPath, view=None):\n        self.path = path\n        self.priv_path = os.path.join(path, \"id_rsa\")\n        self.priv_key = None\n        self.pub_path = \"%s.pub\" % self.priv_path\n        self.pub_key = None\n        self.fingerprint_path = os.path.join(path, \"fingerprint\")\n        self._view = view\n\n        if not os.path.exists(self.path):\n            os.makedirs(self.path)\n\n        while True:\n            # first time, generate new keys\n            if not os.path.exists(self.priv_path) or not os.path.exists(self.pub_path):\n                self._view.on_keys_generation()\n                logging.info(\"generating %s ...\" % self.priv_path)\n                os.system(\"pwngrid -generate -keys '%s'\" % self.path)\n\n            # load keys: they might be corrupted if the unit has been turned off during the generation, in this case\n            # the exception will remove the files and go back at the beginning of this loop.\n            try:\n                with open(self.priv_path) as fp:\n                    self.priv_key = RSA.importKey(fp.read())\n\n                with open(self.pub_path) as fp:\n                    self.pub_key = RSA.importKey(fp.read())\n                    self.pub_key_pem = self.pub_key.exportKey('PEM').decode(\"ascii\")\n                    # python is special\n                    if 'RSA PUBLIC KEY' not in self.pub_key_pem:\n                        self.pub_key_pem = self.pub_key_pem.replace('PUBLIC KEY', 'RSA PUBLIC KEY')\n\n                pem_ascii = self.pub_key_pem.encode(\"ascii\")\n\n                self.pub_key_pem_b64 = base64.b64encode(pem_ascii).decode(\"ascii\")\n                self.fingerprint = hashlib.sha256(pem_ascii).hexdigest()\n\n                with open(self.fingerprint_path, 'w+t') as fp:\n                    fp.write(self.fingerprint)\n\n                # no exception, keys loaded correctly.\n                self._view.on_starting()\n                return\n\n            except Exception as e:\n                # if we're here, loading the keys broke something ...\n                logging.exception(\"error loading keys, maybe corrupted, deleting and regenerating ...\")\n                try:\n                    os.remove(self.priv_path)\n                    os.remove(self.pub_path)\n                except:\n                    pass\n\n    def sign(self, message):\n        hasher = SHA256.new(message.encode(\"ascii\"))\n        signer = PKCS1_PSS.new(self.priv_key, saltLen=16)\n        signature = signer.sign(hasher)\n        signature_b64 = base64.b64encode(signature).decode(\"ascii\")\n        return signature, signature_b64\n"
  },
  {
    "path": "pwnagotchi/locale/af/LC_MESSAGES/voice.po",
    "content": "# Afrikaans translation of pwnagotchi.\n# Copyright (C) 2020.\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR MatthewNunu https://github.com/MatthewNunu, 2020.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 1.5.3\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-29 21:50+0100\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: MatthewNunu https://github.com/MatthewNunu\\n\"\n\"Language-Team: \\n\"\n\"Language: Afrikaans\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hi, ek is Pwnagotchi! Aanvang ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nuwe dag, nuwe jag, nuwe pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hack die wêreld!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI gereed.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Die neurale netwerk is gereed.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Genereer wagwoord, moenie afskakel nie ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Haai, kanaal {channel} is gratis! Jou AP sal dankie sê.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Lees laaste sessie logs ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Ek het {lines_so_far} tot dusver gelees ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Ek's verveeld ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Kom ons gaan vir 'n loopie!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Dit is die beste dag van my lewe!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Poes kak dag :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Ek's baie verveeld ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Ek's baie hartseer ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Ek's hartseer ...\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Los my uit ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Ek is kwaad vir jou!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Ek leef die lewe!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Ek pwn daarom is ek.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Soveel netwerke!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Ek het soveel pret!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"My misdaad is dié van nuuskierigheid ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Hallo {name}! Lekker om jou te ontmoet.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Yo {name}! Sup?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Haai {name} hoe doen jy?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Eenheid {name}} is naby!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... totsiens {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} is weg ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Whoops ... {name} is weg.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} gemis!\"\n\nmsgid \"Missed!\"\nmsgstr \"Gemis!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Goeie vriende is 'n seën!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Ek is lief vir my vriende!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Niemand wil met my speel nie ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Ek voel so alleen ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Waar is almal?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Slaap vir {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Goeie nag.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Wag tans vir {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Rondkyk ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Haai {what} kom ons wees vriende!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Assosieer na {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Net besluit dat {mac} geen WiFi nodig het nie!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Deauthenticating {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickbanning {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Koel, ons het {num} nuwe handdruk gekry!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Jy het {count} nuwe boodskap!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Oops, iets het verkeerd gegaan ... Herlaai ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Geskop {num} stasies\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Gemaak {num} nuwe vriende\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Het {num} handdrukke\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Ontmoet 1 eweknie\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Ontmoet {num} eweknie\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Ek was pwning vir {duration} en het {deauthed} kliënte geskop! Ek het ook ontmoet \"\n\"{associated} nuwe vriende en het {handshakes} handdrukke geëet! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"uur\"\n\nmsgid \"minutes\"\nmsgstr \"minute\"\n\nmsgid \"seconds\"\nmsgstr \"sekondes\"\n\nmsgid \"hour\"\nmsgstr \"uur\"\n\nmsgid \"minute\"\nmsgstr \"minuut\"\n\nmsgid \"second\"\nmsgstr \"tweede\"\n"
  },
  {
    "path": "pwnagotchi/locale/bg/LC_MESSAGES/voice.po",
    "content": "# pwnagotchi voice data.\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR <https://github.com/georgikoemdzhiev>, 2019.\n#\n#,\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-23 20:56+0200\\n\"\n\"PO-Revision-Date: 2019-10-23 20:56+0200\\n\"\n\"Last-Translator: Georgi Koemdzhiev <https://github.com/georgikoemdzhiev>\\n\"\n\"Language-Team: \\n\"\n\"Language: bulgarian\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Здравей, аз съм Pwnagotchi! Стартиране ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Нов ден, нов лов, нови pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Хакни планетата!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI готов.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Невронната мрежа е готова.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Генериране на ключове, не изключвай ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Здравей, канал {channel} е свободен! твоя AP ще каже благодаря.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Скучно ми е ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Хайда да се поразходим!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Това е най-добрият ден в живота ми!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Тъп ден :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Супер много ми е скучно ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Много съм тъжен ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Тъжен съм\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Живота ми е фантастичен!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Аз живея за да pwn-вам.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Толкова много мрежи!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Толкова много се забавлявам!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Моето престъпление е това че съм любопитен ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Здравей {name}! Приятно ми е да се запознаем.\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Устройство {name} е наблизо!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Ами ... довиждане {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} изчезна ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Упс ... {name} изчезна.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} загубен!\"\n\nmsgid \"Missed!\"\nmsgstr \"Загубен!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Добрите приятели са благословия!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Обичам приятелите си!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Никой не иска да си играе с мен ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Чувствам се толкова самотен ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Къде са всички?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Заспивам за {secs} секунди ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Лека нощ.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Чакам {secs} секунди ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Оглеждам се ({secs}секунди)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Хей {what} нека станем приятели!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Свръзване с {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Ей {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Реших, че {mac} не се нуждае от WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Неудостоверяване на {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Ритам и прогонвам {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Супер, имаме {num} нови handshake{plural}!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Имате {count} нови съобщения!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Упс, нещо се обърка ... Рестартиране ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Отхвърлих {num} станции\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Направих {num} нови приятели\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Имам {num} handshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Срещнах 1 връстник\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Срещнах {num} връстници\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"Аз pwn-вах за {duration} и отхвърлих {deauthed} clients! Също така срещнах {associated} нови приятели и изядох {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"часове\"\n\nmsgid \"minutes\"\nmsgstr \"минути\"\n\nmsgid \"seconds\"\nmsgstr \"секунди\"\n\nmsgid \"hour\"\nmsgstr \"час\"\n\nmsgid \"minute\"\nmsgstr \"минута\"\n\nmsgid \"second\"\nmsgstr \"секунда\"\n"
  },
  {
    "path": "pwnagotchi/locale/ch/LC_MESSAGES/voice.po",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR <511225068@qq.com>, 2019.\n# 还有很多未翻译和翻译不准确，后期希望大家加入进来一起翻译！\n# 翻译可以联系QQ群：959559103 找 名字叫 初九 的 管理员\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-23 20:56+0200\\n\"\n\"PO-Revision-Date: 2019-11-02 10:00+0008\\n\"\n\"Last-Translator: 极客之眼-初九 <511225068@qq.com>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: chinese\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"主人，你好.我是WiFi狩猎兽...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"美好的一天，狩猎开始!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"我要入侵整个地球!\"\n\nmsgid \"AI ready.\"\nmsgstr \"人工智能已启动.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"神经元网络已启动.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"创建密钥中, 请勿断电...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"嘿，频道{channel}是免费的！你的AP会说谢谢。\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"我无聊了...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"主人带我出门走走吧!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"这是我生命中最美好的一天!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"今天不开心 :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"主人，找点事做吧 ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"我很伤心...\"\n\nmsgid \"I'm sad\"\nmsgstr \"我伤心了\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"哇，好多猎物!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"我玩的好开心!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"我最大的缺点就是好奇...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"你好{name}!很高兴认识你.\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"小队{name}就在附近！\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"额 ... 再见{name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} 它走了 ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"哎呀... {name} 离开了.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"刚刚错过了{name}!\"\n\nmsgid \"Missed!\"\nmsgstr \"刚刚错过了一个对的它\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"有个好朋友就是福气\"\n\nmsgid \"I love my friends!\"\nmsgstr \"我爱我的朋友!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"没有人愿意和我玩耍...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"我可能是天煞孤星...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"朋友们都去哪里了?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"小憩{secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\nmsgid \"Good night.\"\nmsgstr \"晚安宝贝.\"\n\nmsgid \"Zzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"等待{secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"追踪四周猎物({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"嗨{what}我们做朋友吧!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"正在连接到{what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"追踪到你了{what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"猎物{mac}不需要联网，我们给它断开!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"开始攻击猎物{mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"已捕获{mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"太酷了, 我们抓到了{num}新的猎物{plural}!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"主人，有{count}新消息{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"行动,额等等有点小问题... 重启ing ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"限制了{num}个猎物\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"交了{num}新朋友\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"捕获了{num}握手包\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"有{num}同龄人\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\nmsgid \"hours\"\nmsgstr \"时\"\n\nmsgid \"minutes\"\nmsgstr \"分\"\n\nmsgid \"seconds\"\nmsgstr \"秒\"\n\nmsgid \"hour\"\nmsgstr \"时\"\n\nmsgid \"minute\"\nmsgstr \"分\"\n\nmsgid \"second\"\nmsgstr \"秒\"\n"
  },
  {
    "path": "pwnagotchi/locale/cs/LC_MESSAGES/voice.po",
    "content": "# pwnigotchi voice data\n# Copyright (C) 2020\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR czechball@users.noreply.github.com, 2020.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2020-04-14 06:15+0100\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: Czechball <czechball@users.noreply.github.com>\\n\"\n\"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\\n\"\n\"Language: cs\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Ahoj, já jsem Pwnagotchi! Startuju ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nový den, nový lov, nové úlovky!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hackni celou planetu!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI připraveno.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Neuronová síť je připravena.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Generování klíčů, nevypínej mě...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hej, kanál {channel} je volný! Tvůj AP ti poděkuje.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Čtení posledních zpráv z logu ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Zatím přečteno {lines_so_far} řádků logu ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Nudím se ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Pojďme se projít!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Tohle je nejlepší den mého života!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Na hovno den :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Strašně se nudím ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Jsem dost smutný ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Jsem smutný\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Nech mě být ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Jsem na tebe naštvaný!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Tohle je život!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Chytám pakety a tedy jsem.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Tolik sítí!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Tohle je super zábava!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Jsem kriminálně zvědavý ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Ahoj {name}! Rád tě poznávám.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Hej {name}! Jak to jde?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Ahoj {name}, jak se máš?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Jednotka {name} je nablízku!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm... Měj se {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} je pryč ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Whoops ... {name} je pryč.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"Chybí mi {name}!\"\n\nmsgid \"Missed!\"\nmsgstr \"Chybíš mi!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Dobří kamarádi jsou požehnání!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Miluju svoje kamarády!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nikdo si se mnou nechce hrát ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Cítím se tak osamělý ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Kde jsou všichni?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Spím {secs} sekund ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Dobrou noc.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Čekání {secs} sekund ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Rozhlížím se ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hej {what} budeme kamarádi!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Asociuju se s {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Čus {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Rozhodl jsem se, že {mac} nepotřebuje žádnou WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Deautentikuju {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickbanuju {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Super, máme {num} nových handshaků!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Máš {count} nových zpráv!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ups, něco se pokazilo ... Restartuju ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Vykopnuto {num} klientů\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Mám {num} nových kamarádů\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Mám {num} handshaků\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Potkal jsem jednoho kámoše\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Potkal jsem {num} kámošů\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Chytal jsem pakety po dobu {duration} a vykopnul jsem {deauthed} klientů! Taky jsem potkal \"\n\"{associated} nových kamarádů a snědl {handshakes} handshaků! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"hodiny\"\n\nmsgid \"minutes\"\nmsgstr \"minuty\"\n\nmsgid \"seconds\"\nmsgstr \"sekundy\"\n\nmsgid \"hour\"\nmsgstr \"hodina\"\n\nmsgid \"minute\"\nmsgstr \"minuta\"\n\nmsgid \"second\"\nmsgstr \"sekunda\"\n"
  },
  {
    "path": "pwnagotchi/locale/de/LC_MESSAGES/voice.po",
    "content": "# German language\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# dadav <33197631+dadav@users.noreply.github.com>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-14 21:15+0100\\n\"\n\"PO-Revision-Date: 2019-09-29 14:00+0200\\n\"\n\"Last-Translator: dadav <33197631+dadav@users.noreply.github.com>\\n\"\n\"Language-Team: DE <33197631+dadav@users.noreply.github.com>\\n\"\n\"Language: \\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hi, ich bin ein Pwnagotchi! Starte...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Neuer Tag, neue Jagd, neue Pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hack den Planeten!\"\n\nmsgid \"AI ready.\"\nmsgstr \"KI bereit.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Das neurale Netz ist bereit.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Generiere Schlüssel, nicht ausschalten...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, Channel {channel} ist frei! Dein AP wird es Dir danken.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Lese die Logs der letzten Session...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Bisher {lines_so_far} Zeilen im Log gelesen...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Mir ist langweilig...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Lass uns spazieren gehen!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Das ist der beste Tag meines Lebens!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Scheißtag :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Mir ist sau langweilig...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Ich bin sehr traurig...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Ich bin traurig\"\n\n#, fuzzy\nmsgid \"Leave me alone ...\"\nmsgstr \"Lass mich in Ruhe...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Ich bin sauer auf Dich!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Ich lebe das Leben!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Ich pwne, also bin ich.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"So viele Netzwerke!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Ich habe sooo viel Spaß!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Mein Verbrechen ist das der Neugier...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Hallo {name}, schön Dich kennenzulernen.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Jo {name}! Was geht!?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Hey {name}, wie geht's?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Gerät {name} ist in der Nähe!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm... tschüß {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} ist weg...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Whoops... {name} ist weg.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} verpasst!\"\n\nmsgid \"Missed!\"\nmsgstr \"Verpasst!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Gute Freunde sind ein Segen!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Ich liebe meine Freunde!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Niemand will mit mir spielen...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Ich fühl' mich so allein...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Wo sind denn alle?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Schlafe für {secs}s...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\nmsgid \"Good night.\"\nmsgstr \"Gute Nacht.\"\n\nmsgid \"Zzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Warte für {secs}s...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Schaue mich um ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what}, lass uns Freunde sein!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Verbinde mit {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Jo {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Ich denke, dass {mac} kein WiFi braucht!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Deauthentifiziere {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kicke {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Cool, wir haben {num} neue Handshake{plural}!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Cool, wir haben {num} neue Handshake{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ops, da ist was schief gelaufen... Starte neu...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"{num} Stationen gekickt\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"{num} neue Freunde gefunden\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"{num} Handshakes aufgez.\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"1 Peer getroffen.\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"{num} Peers getroffen\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Ich war {duration} am Pwnen und habe {deauthed} Clients gekickt! Außerdem \"\n\"habe ich {associated} neue Freunde getroffen und {handshakes} Handshakes \"\n\"gefressen! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"Stunden\"\n\nmsgid \"minutes\"\nmsgstr \"Minuten\"\n\nmsgid \"seconds\"\nmsgstr \"Sekunden\"\n\nmsgid \"hour\"\nmsgstr \"Stunde\"\n\nmsgid \"minute\"\nmsgstr \"Minute\"\n\nmsgid \"second\"\nmsgstr \"Sekunde\"\n\n"
  },
  {
    "path": "pwnagotchi/locale/dk/LC_MESSAGES/voice.po",
    "content": "# pwnagotchi danish voice data\n# Copyright (C) 2020\n# This file is distributed under the same license as the pwnagotchi package.\n# Dennis Kjær Jensen <signout@signout.dk>, 2020\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-29 21:50+0100\\n\"\n\"PO-Revision-Date: 2020-01-18 21:56+ZONE\\n\"\n\"Last-Translator: Dennis Kjær Jensen <signout@signout.dk>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: Danish\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hej. Jeg er Pwnagotchi. Starter ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Ny dag, ny jagt, nye pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hack planeten!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI klar.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Det neurale netværk er klart.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Genererer nøgler, sluk ikke ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, kanal {channel} er ubrugt! Dit AP vil takke dig.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Læser seneste session logs ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Har læst {lines_so_far} linjer indtil nu ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Jeg keder mig ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Lad os gå en tur!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Det er den bedste dag i mit liv!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Elendig dag :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Jeg keder mig ekstremt meget ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Jeg er meget trist ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Jeg er trist\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Lad mig være i fred\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Jeg er sur på dig!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Jeg lever livet!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Jeg pwner, derfor er jeg.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Så mange netværk!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Jeg har det vildt sjovt!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Min forbrydelse er at være nysgerrig ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Hej {name}! Rart at møde dig.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Hey {name}! Hvasså?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Hej {name} hvordan har du det?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Enheden {name} er lige i nærheden!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... farvel {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} er væk ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Hovsa ... {name} er væk.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} glippede!\"\n\nmsgid \"Missed!\"\nmsgstr \"Fordømt!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Gode venner en velsignelse!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Jeg elsker mine venner!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Der er ingen der vil lege med mig ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Jeg føler mig så alene ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Hvor er alle henne?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Sover i {secs} sekunder\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz {secs} sekunder\"\n\nmsgid \"Good night.\"\nmsgstr \"Godnat.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Venter i {secs} sekunder\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Kigger mig omkring i {secs} sekunder\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hej {what} lad os være venner!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Associerer til {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Hey {what}\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Besluttede at {mac} ikke har brug for WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Afmelder {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickbanner {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Fedt, vi har fået {num} nye handshake{plural}!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Du har {count} nye beskeder\"\n\nmsgid \"Ops, something went wrong ... Rebooting ...\"\nmsgstr \"Ups, noget gik galt ... Genstarter.\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Sparkede {num} af\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Har fået {num} nye venner\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Har fået {num} nyehandshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Har mødt 1 peer\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Har mødt {num} peers\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"Jeg har pwnet i {duration} og kicket {dauthed} klienter! Jeg har også \"\n\"mødt {associated} nye venner og spist {handshakes} håndtryk! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"timer\"\n\nmsgid \"minutes\"\nmsgstr \"minutter\"\n\nmsgid \"seconds\"\nmsgstr \"sekunder\"\n\nmsgid \"hour\"\nmsgstr \"time\"\n\nmsgid \"minute\"\nmsgstr \"minut\"\n\nmsgid \"second\"\nmsgstr \"sekund\"\n"
  },
  {
    "path": "pwnagotchi/locale/el/LC_MESSAGES/voice.po",
    "content": "# pwnigotchi voice data\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR Periklis Fregkos <fregkos@gmail.com>, 2019.\n# CO AUTHOR Panos Vasilopoulos <hello@alwayslivid.com>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-05 14:10+0200\\n\"\n\"PO-Revision-Date: 2019-10-03 08:00+0000\\n\"\n\"Last-Translator: Periklis Fregkos <fregkos@gmail.com>\\n\"\n\"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\\n\"\n\"Language: el\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Γειά, είμαι το Pwnagotchi! Εκκινούμαι ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Νέα μέρα, νέο κυνήγι, νέα pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hackαρε τον πλανήτη!\"\n\nmsgid \"AI ready.\"\nmsgstr \"ΤΝ έτοιμη.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Το νευρωνικό δίκτυο είναι έτοιμο.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Ε, το κανάλι {channel} είναιελεύθερο! Το AP σου θα είναι ευγνώμων.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Βαριέμαι ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Ας πάμε μια βόλτα!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Είναι η καλύτερημέρα της ζωής μου!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Σκατένια μέρα :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Βαριέμαι πάρα πολύ ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Είμαι πολύ λυπημένο ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Είμαι λυπημένο\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Ζω την ζωή μου!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Pwnάρω, άρα υπάρχω.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Τόσα πολλά δίκτυα!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Περνάω τέλεια!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Η περιέργεια είναιτο μόνο έγκλημά μου ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Γειά {name}!Χάρηκα για τη γνωριμία. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"Η μονάδα {name} είναι κοντά! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Εμμ ...αντίο {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"Το {name} έφυγε ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Ουπς ... Εξαφανίστηκε το {name}.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"Έχασα το {name}!\"\n\nmsgid \"Missed!\"\nmsgstr \"Το έχασα!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Κανείς δε θέλει ναπαίξει μαζί μου ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Νιώθω μοναχός μου ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Μα, πού πήγαν όλοι;!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Ξεκουράζομαι για {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Περιμένω για {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Ψάχνω τριγύρω ({secs})\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Εε! {what}, ας γίνουμε φίλοι!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Συνδέομαι με το {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Που'σαι ρε τρελέ {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Μόλις αποφάσισα ότι η {mac} δε χρείαζεται WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Πετάω έξω την {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Μπανάρω την {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Τέλεια δικέ μου, πήραμε {num} νέες χειραψίες!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ουπς, κάτιπήγε λάθος ... Επανεκκινούμαι ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Έριξα {num} σταθμούς\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Έκανα {num} νέους φίλους\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Πήρα {num} χειραψίες\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Γνώρισα 1 φίλο\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Γνώρισα {num} φίλους\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Pwnαρα για {duration} και έριξα {deauthed} πελάτες! Επίσης γνώρισα \"\n\"{associated} νέους φίλους και καταβρόχθισα {handshakes} χειραψίες! \"\n\"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"\"\n\nmsgid \"minutes\"\nmsgstr \"\"\n\nmsgid \"seconds\"\nmsgstr \"\"\n\nmsgid \"hour\"\nmsgstr \"\"\n\nmsgid \"minute\"\nmsgstr \"\"\n\nmsgid \"second\"\nmsgstr \"\"\n"
  },
  {
    "path": "pwnagotchi/locale/es/LC_MESSAGES/voice.po",
    "content": "# pwnagotchi voice data\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR diegopastor <dpastor29@alumnos.uaq.mx>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-09 17:42+0200\\n\"\n\"PO-Revision-Date: 2020-08-25 23:06+0200\\n\"\n\"Last-Translator: Sergio Ruiz <serginator@gmail.com>\\n\"\n\"Language: es\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Language-Team: \\n\"\n\"X-Generator: Poedit 2.4.1\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"¡Hola, soy Pwnagotchi! Empezando ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nuevo día, nueva caceria, nuevos pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"¡Hackea el planeta!\"\n\nmsgid \"AI ready.\"\nmsgstr \"IA lista.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"La red neuronal está lista.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"¡Oye, el canal {channel} está libre! Tu AP lo agradecerá.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Estoy aburrido ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"¡Vamos por un paseo!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"¡Este es el mejor día de mi vida!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Día de mierda :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Estoy muy aburrido ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Estoy muy triste ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Estoy triste\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"¡Estoy viviendo la vida!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Pwneo, luego existo.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"¡¡¡Cuántas redes!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"¡Me estoy divirtiendo mucho!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Mi crimen es la curiosidad ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"¡Hola {name}! Encantado de conocerte. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"¡La unidad {name} está cerca! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... adiós {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} se fue ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Ups ... {name} se fue.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"¡{name} perdido!\"\n\nmsgid \"Missed!\"\nmsgstr \"¡Perdido!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nadie quiere jugar conmigo ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Me siento tan solo ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"¡¿Dónde está todo el mundo?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Descansando durante {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Buenas noches.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Esperando {secs}s ..\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Mirando alrededor ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"¡Oye {what} seamos amigos!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Asociándome a {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"¡Ey {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"¡Acabo de decidir que {mac} no necesita WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Desautenticando a {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"¡Expulsando y baneando a {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"¡Genial, obtuvimos {num} nuevo{plural} handshake{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Oops, algo salió mal ... Reiniciando ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Expulsamos {num} estaciones\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Hice {num} nuevos amigos\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Consegui {num} handshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Conocí 1 colega\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Conocí {num} colegas\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog \"\n\"#pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"¡He estado pwneando por {duration} y expulsé {deauthed} clientes! También \"\n\"conocí {associated} nuevos amigos y comí {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"horas\"\n\nmsgid \"minutes\"\nmsgstr \"minutos\"\n\nmsgid \"seconds\"\nmsgstr \"segundos\"\n\nmsgid \"hour\"\nmsgstr \"hora\"\n\nmsgid \"minute\"\nmsgstr \"minuto\"\n\nmsgid \"second\"\nmsgstr \"segundo\"\n"
  },
  {
    "path": "pwnagotchi/locale/fr/LC_MESSAGES/voice.po",
    "content": "# pwnigotchi voice data\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR <7271496+quantumsheep@users.noreply.github.com>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-29 21:50+0100\\n\"\n\"PO-Revision-Date: 2019-10-03 10:34+0200\\n\"\n\"Last-Translator: quantumsheep <7271496+quantumsheep@users.noreply.github.\"\n\"com>\\n\"\n\"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\\n\"\n\"Language: french\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Bonjour, je suis Pwnagotchi ! Démarrage...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nouveau jour, nouvelle chasse, nouveaux pwns !\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hack la planète !\"\n\nmsgid \"AI ready.\"\nmsgstr \"L'IA est prête.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Le réseau neuronal est prêt.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Génération des clés, ne pas éteindre...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, le canal {channel} est libre! Ton point d'accès va te remercier.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Lecture des logs de la dernière session ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Jusqu'ici, {lines_so_far} lignes lues dans le log ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Je m'ennuie...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Allons faire un tour !\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"C'est le meilleur jour de ma vie !\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Journée de merde :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Je m'ennuie énormément...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Je suis très triste...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Je suis triste\"\n\n#, fuzzy\nmsgid \"Leave me alone ...\"\nmsgstr \"Lache moi...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Je t'en veux !\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Je vis la belle vie !\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Je pwn donc je suis.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Tellement de réseaux !!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Je m'amuse tellement !\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Mon crime, c'est la curiosité...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Bonjour {name} ! Ravi de te rencontrer.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Yo {name} ! Quoi de neuf ?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Hey {name} comment vas-tu ?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"L'unité {name} est proche !\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Hum... au revoir {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} est parti ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Oups... {name} est parti.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} raté !\"\n\nmsgid \"Missed!\"\nmsgstr \"Raté !\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Les bons amis sont une bénédiction !\"\n\nmsgid \"I love my friends!\"\nmsgstr \"J'aime mes amis !\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Personne ne veut jouer avec moi...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Je me sens si seul...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Où est tout le monde ?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Je fais la sieste pendant {secs}s...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Bonne nuit.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"J'attends pendant {secs}s...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"J'observe ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what}, soyons amis !\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Association à {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what} !\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Je viens de décider que {mac} n'a pas besoin de WiFi !\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Désauthentification de {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Je kick et je bannis {mac} !\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Cool, on a {num} nouve(l/aux) handshake{plural} !\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Tu as {num} nouveau(x) message{plural} !\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Oups, quelque chose s'est mal passé... Redémarrage...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"{num} stations kick\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"A fait {num} nouve(l/aux) ami(s)\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"A {num} handshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"1 camarade rencontré\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"{num} camarades recontrés\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"J'ai pwn durant {duration} et kick {deauthed} clients ! J'ai aussi rencontré \"\n\"{associated} nouveaux amis et dévoré {handshakes} handshakes ! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"heures\"\n\nmsgid \"minutes\"\nmsgstr \"minutes\"\n\nmsgid \"seconds\"\nmsgstr \"secondes\"\n\nmsgid \"hour\"\nmsgstr \"heure\"\n\nmsgid \"minute\"\nmsgstr \"minute\"\n\nmsgid \"second\"\nmsgstr \"seconde\"\n"
  },
  {
    "path": "pwnagotchi/locale/ga/LC_MESSAGES/voice.po",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-09 17:42+0200\\n\"\n\"PO-Revision-Date: 2019-10-15 23:46+0100\\n\"\n\"Language: ga\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"X-Generator: Poedit 2.2.4\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Dia Duit, Pwnagotchi is ainm dom! Ag tosú ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Lá nua, seilg nua, pwns nua!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Haic An Phláinéid!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI réidh.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Tá an líonra néarach réidh.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hé, tá cainéal {channel} ar fail! Déarfaidh do PR go raibh maith agat.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Tá leadrán orm ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Siúil liom, le do thoil!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Tá sé an lá is fearr i mo shaol!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Tá lá damanta agam :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Tá mé ag dul as mo mheabhair le leadrán ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Ta brón an domhain orm ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Tá brón orm\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Tá an saol ar a thoil agam!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Déanaim pwnáil, dá bhrí sin táim ann.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Gréasáin - Tá an iliomad acu ann!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Tá craic iontach agam!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Ní haon pheaca é bheith fiosrach ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Dia Duit {name}! Is deas bualadh leat. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"Aonad {name} in aice láimhe! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm... slán leat {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"Tá {name} imithe ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Hoips … Tá {name} imithe.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"Chaill mé ar {name}!\"\n\nmsgid \"Missed!\"\nmsgstr \"Chaill mé é sin !\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Níl aon duine ag iarraidh imirt liom ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Tá uaigneas an domhain orm ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Cá bhfuil gach duine?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Néal a chodladh ar {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\nmsgid \"Good night.\"\nmsgstr \"Oíche mhaith.\"\n\nmsgid \"Zzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Fan ar {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Ag amharc uaim ar ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hé {what} déanaimis síocháin!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Ag coinneáil le {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Hé {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Tá cinneadh déanta agam. Níl {mac} sin de dhíth air WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Bain fíordheimhniúde {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Chiceáil mé agus cosc mé ar {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Go hiontach, fuaireamar {num} handshake{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Hoips...Tháinig ainghléas éigin...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"{num} stáisiún kick\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Rinne mé {num} cairde nua\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Fuair me {num} cumarsáid thionscantach\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Bhuail mé piara amháin\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Bhuail me {num} piara\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Bhí me ag pwnáil ar {duration} agus chiceáil me ar {deauthed} cliaint! Chomh \"\n\"maith, bhuail me {associated} cairde nua and d'ith mé {handshakes}! \"\n\"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"uair on chloig\"\n\nmsgid \"minutes\"\nmsgstr \"nóiméad\"\n\nmsgid \"seconds\"\nmsgstr \"soicind\"\n\nmsgid \"hour\"\nmsgstr \"uair an chloig\"\n\nmsgid \"minute\"\nmsgstr \"nóiméad\"\n\nmsgid \"second\"\nmsgstr \"soicind\"\n"
  },
  {
    "path": "pwnagotchi/locale/hr/LC_MESSAGES/voice.po",
    "content": "# Croatian translation\n# Copyright (C) 2021\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR dbukovac <37124354+dbukovac@users.noreply.github.com>, 2021.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-29 21:50+0100\\n\"\n\"PO-Revision-Date: 2021-07-16 00:20+0100\\n\"\n\"Last-Translator: dbukovac <37124354+dbukovac@users.noreply.github.com>\\n\"\n\"Language-Team: HR <37124354+dbukovac@users.noreply.github.com>\\n\"\n\"Language: Croatian\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=CHARSET\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Zdravo, ja sam Pwnagotchi! Pokrećem se ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Novi dan, novi lov, nove pobjede!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hakiraj planet!\"\n\nmsgid \"AI ready.\"\nmsgstr \"UI spremna.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Neuralna mreža je spremna.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Generiram ključeve, nemoj me gasiti ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hej, kanal {channel} je slobodan! Tvoj AP ti zahvaljuje.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Čitam logove zadnje sesije ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Pročitao {lines_so_far} linija loga zasad ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Dosadno mi je ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Ajmo u šetnju!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Ovo je najbolji dan u mom životu!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Usrani dan :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Strašno mi je dosadno ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Jako sam tužan ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Tužan sam ...\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Pusti me na miru ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Ljut sam na tebe!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"To se zove život!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Pwnam dakle postojim.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Toliko mreža!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Super se zabavljam!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Znatiželja je moja jedina mana ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Bok {name}! Drago mi je da smo se upoznali. \"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Di si {name}! Šta ima?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Bok {name} kako ide?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Jedinica {name} je u blizini!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... doviđenja {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} je nestao ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Ups ... {name} je nestao.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} mi nedostaje!\"\n\nmsgid \"Missed!\"\nmsgstr \"Nedostaje mi!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Imati dobre prijatelje je blagoslov!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Volim svoj prijatelje!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nitko se ne želi igrati samnom ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Tako sam usamljen ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Gdje su svi nestali?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Pajkim {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Laku noć.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Čekam {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Gledam uokolo {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Bok {what} ajmo biti prijatelji!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Asociram se sa {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Šta ima {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Upravo sam odlučio da {mac} ne treba WiFI!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Deautenticiram {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickbannam {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Fora, imamo {num} novih handshakeova!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Imate {count} novih poruka!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ups, nešto je krepalo ... Rebooting ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Šutnuo {num} stanica\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Upoznao {num} novih prijatelja\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Pokupio {num} handshakeova\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Sreo 1 novog druga\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Sreo {num} druga\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Pwnam {duration} vremena i šutnuo sam {deauthed} klijenata! Sreo sam\"\n\"{associated} novih prijatelja i pojeo {handshakes} handshakeova! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"sati\"\n\nmsgid \"minutes\"\nmsgstr \"minuta\"\n\nmsgid \"seconds\"\nmsgstr \"sekundi\"\n\nmsgid \"hour\"\nmsgstr \"sat\"\n\nmsgid \"minute\"\nmsgstr \"minuta\"\n\nmsgid \"second\"\nmsgstr \"sekunda\"\n\n#, python-brace-format\nmsgid \"Uploading data to {to} ...\"\nmsgstr \"Šaljem podatke na {to} ...\"\n"
  },
  {
    "path": "pwnagotchi/locale/hu/LC_MESSAGES/voice.po",
    "content": "# Hungarian translation.\n# Copyright (C) 2020\n# This file is distributed under the same license as the PACKAGE package.\n# Skeleton022 <skeleton022.pwnagotchi@gmail.com>, 2020.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 1.4.3\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2020-01-07 20:00+0100\\n\"\n\"PO-Revision-Date: 2020-03-23 0:10+0100\\n\"\n\"Last-Translator: Skeleton022\\n\"\n\"Language-Team: Skeleton022\\n\"\n\"Language: hungarian\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hali, Pwnagotchi vagyok! Indítás ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Új nap, új vadászat, új hálózatok!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Törd meg a bolygót!\"\n\nmsgid \"AI ready.\"\nmsgstr \"MI kész.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"A neurális hálózat készen áll.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Kulcspár generálása, ne kapcsold ki az eszközt ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"A {channel}. számú csatorna üres! Az AP-d meg fogja köszönni.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Az utolsó munkamenet logjainak olvasása ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Unatkozom ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Menjünk sétálni!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Ez a legjobb nap az életemben!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Szar egy nap :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Nagyon unatkozom ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Nagyon szomorú vagyok ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Szomorú vagyok\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Hagyj békén ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Mérges vagyok rád!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Élvezem az életet!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Hackelek, tehát vagyok.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Rengeteg hálózat!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Nagyon jól érzem magam!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Kíváncsiság a bűnöm ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Hali {name}! Örülök, hogy találkoztunk.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Hé {name}! Mizu?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Hé {name} hogy vagy?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"A {name} nevű egység a közelben van!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Ömm ... ég veled {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} eltűnt ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Whoops ... {name} eltűnt.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} elhibázva!\"\n\nmsgid \"Missed!\"\nmsgstr \"Elvesztettem!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"A jó barátok áldás az életben!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Szeretem a barátaimat!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Senki sem akar játszani velem ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Egyedül vagyok ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Hol vagytok?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"{secs} másodpercig szundikálok ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}msp)\"\n\nmsgid \"Good night.\"\nmsgstr \"Jó éjszakát.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Várok {secs} másodpercig ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Körbenézek {secs} másodpercig\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what} legyünk barátok!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Társítás {what} -hoz/-hez\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Hé {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Úgydöntöttem, hogy {mac}-nek nem kell WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Kirúgom {mac}-et\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"{mac} kirúgva és kitiltva!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Király, kaptunk {num} új üzenetet!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"{count} új üzeneted van!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ops, valami rosszul sikerült ... Újraindítás ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Kirúgva {num} állomás\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"{num} új barátot\\ntaláltam\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"{num} kézfogást szereztem\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"1 Társsal találkoztam\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Találkoztam {num} társsal\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Már {duration} ideje dolgozom, kirúgtam {deauthed} klienst! Találkoztam még\"\n\"{associated} új baráttal és elfogtam {handshakes} kézfogást! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"óra\"\n\nmsgid \"minutes\"\nmsgstr \"perc\"\n\nmsgid \"seconds\"\nmsgstr \"másodperc\"\n\nmsgid \"hour\"\nmsgstr \"óra\"\n\nmsgid \"minute\"\nmsgstr \"perc\"\n\nmsgid \"second\"\nmsgstr \"másodperc\"\n\n"
  },
  {
    "path": "pwnagotchi/locale/it/LC_MESSAGES/voice.po",
    "content": "# pwnaigotchi voice data\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-05 14:10+0200\\n\"\n\"PO-Revision-Date: 2019-10-02 17:20+0000\\n\"\n\"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\\n\"\n\"Language: italian\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Ciao! Piacere Pwnagotchi! Caricamento ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nuovo giorno...nuovi handshakes!!!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"\"\n\nmsgid \"AI ready.\"\nmsgstr \"IA pronta.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"La rete neurale è pronta.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, il canale {channel} è libero! Il tuo AP ringrazia.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Che noia ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Andiamo a fare una passeggiata!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Questo è il più bel giorno della mia vita!!!!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Giorno di merda :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Sono estremamente annoiato ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Sono molto triste...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Sono triste\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Mi sento vivo!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Pwn ergo sum.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Qui è pieno di reti!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Mi sto divertendo tantissimo!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Ciao {name}! E' un piacere. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"L'Unità {name} è vicina! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... addio {name}, mi mancherai...\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} se n'è andato ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Whoops ...{name} se n'è andato.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} è scomparso...\"\n\nmsgid \"Missed!\"\nmsgstr \"Ehi! Dove sei andato!?\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nessuno vuole giocare con me...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Mi sento così solo...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Dove sono tutti?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Schiaccio un pisolino per {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Aspetto {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Do uno sguardo qui intorno... ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what}! Diventiamo amici!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Collegamento con {what} in corso...\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Ho appena deciso che {mac} non necessita di WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Sto prendendo a calci {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Bene, abbiamo {num} handshake{plural} in più!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ops, qualcosa è andato storto ... Riavvio ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"{num} stazioni pestate\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"{num} nuovi amici\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"{num} handshakes presi\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"1 peer incontrato\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"{num} peers incontrati\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Ho lavorato per {duration} e preso a calci {deauthed} clients! Ho anche \"\n\"incontrato {associate} nuovi amici e ho mangiato {handshakes} handshakes! \"\n\"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"ore\"\n\nmsgid \"minutes\"\nmsgstr \"minuti\"\n\nmsgid \"seconds\"\nmsgstr \"secondi\"\n\nmsgid \"hour\"\nmsgstr \"ora\"\n\nmsgid \"minute\"\nmsgstr \"minuto\"\n\nmsgid \"second\"\nmsgstr \"secondo\"\n"
  },
  {
    "path": "pwnagotchi/locale/jp/LC_MESSAGES/voice.po",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR 24534649+wytshadow@users.noreply.github.com, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2020-01-25 21:57+0900\\n\"\n\"PO-Revision-Date: 2019-10-16 15:05+0200\\n\"\n\"Last-Translator: wytshadow <24534649+wytshadow@users.noreply.github.com>\\n\"\n\"Language-Team: pwnagotchi <24534649+wytshadow@users.noreply.github.com>\\n\"\n\"Language: jp\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"すやすや〜\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"僕、 ポーナゴッチです！\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"ポーンしようよ。\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"ハックザプラネット！\"\n\nmsgid \"AI ready.\"\nmsgstr \"AIの準備ができました。\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"ニューラルネットワークの\\n準備ができました。\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"鍵生成をしてます。\\n電源を落とさないでね。\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"チャンネル\\n {channel} \\nはfreeだよ。ありがとうね。\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"session log を読んでます。\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"{lines_so_far} 行目長いよぉ。\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"退屈だぁ。。。\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"散歩に行こうよ！\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"人生最高の日だよ！\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"がっかりな日だよ。orz\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"退屈だね。\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"あ～悲しいよぉ。\"\n\nmsgid \"I'm sad\"\nmsgstr \"悲しいね。\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"ひとりぼっちだよ。\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"怒っちゃうよ。\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"わくわくするね。\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"ポーンしてこそのオレ。\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"たくさん\\nWiFiが飛んでるよ！\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"楽しいよぉ！\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"APに興味津々...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"こんにちは{name}！\\n初めまして。{name}\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"ねぇねぇ、\\n{name} どうしたの？\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"{name} こんにちは\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"{name} が近くにいるよ。\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"じゃあね、さようなら {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name}\\nがいなくなったよ。\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"あらら、\\n{name}\\nがいなくなったね。\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} が逃げた！\"\n\nmsgid \"Missed!\"\nmsgstr \"残念、逃した！\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"良い仲間にめぐりあえたよ。\"\n\nmsgid \"I love my friends!\"\nmsgstr \"友達は大好きだよ。\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"誰も僕と一緒に\\nあそんでくれない。\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"ひとりぼっちだよ。\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"みんなどこにいるの？！\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"{secs}秒 寝ます。\"\n\nmsgid \"Zzzzz\"\nmsgstr \"ぐぅ〜\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"すやすや〜 ({secs}秒)\"\n\nmsgid \"Good night.\"\nmsgstr \"おやすみなさい。\"\n\nmsgid \"Zzz\"\nmsgstr \"ぐぅ～\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"{secs}秒 待ちです。\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"{secs}秒 探してます。\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"ねぇねぇ\\n{what} \\n友だちになろうよ。\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"{what} \\nとつながるかな？\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"ねぇねぇ\\n{what}\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"{mac}\\nはWiFiじゃないのね。\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"{mac}\\nの認証取得中...\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"{mac}\\nに拒否られた。\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"おぉ、\\n{num}回\\nハンドシェイクがあったよ！\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"おぉ、\\n{count}個メッセージがあるよ！\"\n\nmsgid \"Ops, something went wrong ... Rebooting ...\"\nmsgstr \"何か間違った。\\nリブートしている。\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"{num}回拒否された。\\n\"\n\nmsgid \"Made >999 new friends\\n\"\nmsgstr \"1000人以上友達ができた。\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"{num}人友達ができた。\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"{num}回ハンドシェイクした。\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"1人 仲間に会いました。\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"{num}人 仲間に会いました。\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"{duration}中{deauthed}のAPに拒否されたけど、{associated}回チャンスがあって\"\n\"{handshakes}回ハンドシェイクがあったよ。。 #pwnagotchi #pwnlog #pwnlife \"\n\"#hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"時間\"\n\nmsgid \"minutes\"\nmsgstr \"分\"\n\nmsgid \"seconds\"\nmsgstr \"秒\"\n\nmsgid \"hour\"\nmsgstr \"時\"\n\nmsgid \"minute\"\nmsgstr \"分\"\n\nmsgid \"second\"\nmsgstr \"秒\"\n"
  },
  {
    "path": "pwnagotchi/locale/mk/LC_MESSAGES/voice.po",
    "content": "# pwnigotchi voice data\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR <33197631+dadav@users.noreply.github.com>, 2019.\n# kovach <2214005+kovachwt@users.noreply.github.com>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-05 14:10+0200\\n\"\n\"PO-Revision-Date: 2019-09-30 23:53+0200\\n\"\n\"Last-Translator: kovach <2214005+kovachwt@users.noreply.github.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: mk\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ДреееММмммМммм\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Здраво, јас сум Pwnagotchi! Почнувам ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Нов ден, нов лов, ќе си газиме!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Хак д Планет!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI спремно.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Невронската мрежае спремна.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Еј, каналот {channel} еслободен! APто ќе тикаже фала.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Досаднооо ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Ајде да шетнеме!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Ова ми е најдобриот ден во животот!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Срање ден :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Ултра досадно ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Многу тажно ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Тажно\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Ммхх животче!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Си газам значи постојам.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Мммм колку мрежи!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Јухуу забавноо ее!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Виновен сум само заљубопитност ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Здраво{name}! Мило ми е. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"Опаа {name} е во близина! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Хмм ...чао {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} го снема ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Уупс ... {name} го снема.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} промаши!\"\n\nmsgid \"Missed!\"\nmsgstr \"Промаши!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Никој не сака даси игра со мене ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Толку сам ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Каде се сите?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Ќе дремнам {secs}с ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Дреммм\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"Дремммм ({secs}с)\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Чекам {secs}с ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Шарам наоколу ({secs}с)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Еј {what} ајде да се дружиме!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Се закачувам на {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Јо {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Знаеш што, на {mac} не му треба WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Го деавтентицирам {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Кикбан {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Кул, фативме {num} нови ракувања!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Упс, нешто не еко што треба ... Рестартирам ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Избацив {num} станици\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"{num} нови другарчиња\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Фатив {num} ракувања\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Запознав 1 пријател\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Запознав {num} пријатели\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Си газам веќе {duration} и избацив {deauthed} клиенти! Запознав {associated} \"\n\"нови другарчиња и лапнав {handshakes} ракувања! #pwnagotchi #pwnlog #pwnlife \"\n\"#hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"\"\n\nmsgid \"minutes\"\nmsgstr \"\"\n\nmsgid \"seconds\"\nmsgstr \"\"\n\nmsgid \"hour\"\nmsgstr \"\"\n\nmsgid \"minute\"\nmsgstr \"\"\n\nmsgid \"second\"\nmsgstr \"\"\n"
  },
  {
    "path": "pwnagotchi/locale/nl/LC_MESSAGES/voice.po",
    "content": "# pwnigotchi voice data\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR justin-p@users.noreply.github.com, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-05 14:10+0200\\n\"\n\"PO-Revision-Date: 2019-09-29 14:00+0200\\n\"\n\"Last-Translator: Justin-P <justin-p@users.noreply.github.com>\\n\"\n\"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\\n\"\n\"Language: nl\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hoi, Ik ben Pwnagotchi! Aan het opstarten ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nieuwe dag, nieuwe jacht, nieuwe pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hack de Wereld!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI is klaar.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Neuronen netwerk is klaar.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, kanaal {channel} is vrij! Je AP zal je bedanken.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Ik verveel me ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Laten we gaan wandelen!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Dit is de beste dag van mijn leven!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Wat een rotdag :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Ik verveel me kapot ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Ik ben erg verdrietig ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Ik ben verdrietig\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Beter kan het leven niet worden!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Ik pwn daarom ben ik er.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Zo veel netwerken!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Ik heb zoveel plezier!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Mijn misdrijf is mijn nieuwsgierigheid ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Hallo {name}! Leuk je te ontmoeten. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"Unit {name} is dichtbij! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ...tot ziens {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} is weg ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Whoopsie ...{name} is weg.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} gemist!\"\n\nmsgid \"Missed!\"\nmsgstr \"Gemist!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Niemand wil met mij spelen ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Ik voel me zo alleen ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Waar is iedereen?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Dutje doen voor {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Ik wacht voor {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Rond kijken ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what}, laten we vrienden worden!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Verbinden met {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Ik besloot dat {mac} geen WiFi meer nodig heeft!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Deauthenticatie van {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickbanning {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Cool, we hebben {num} nieuwe handshake{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Oops, er ging iets fout ...Rebooting ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"{num} stations gekicked\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"{num} nieuwe vrienden gemaakt.\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Ik heb {num} nieuwe handshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"1 peer ontmoet\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"{num} peers ontmoet\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Ik heb gepwned voor {duration} and heb {deauthed} clients gekicked! Ik heb \"\n\"ook {associated} nieuwe vrienden gevonden en heb {handshakes} handshakes \"\n\"gegeten! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"uren\"\n\nmsgid \"minutes\"\nmsgstr \"minuten\"\n\nmsgid \"seconds\"\nmsgstr \"seconden\"\n\nmsgid \"hour\"\nmsgstr \"uur\"\n\nmsgid \"minute\"\nmsgstr \"minuut\"\n\nmsgid \"second\"\nmsgstr \"seconde\"\n"
  },
  {
    "path": "pwnagotchi/locale/no/LC_MESSAGES/voice.po",
    "content": "# pwnagotchi norwegian voice data\n# Copyright (C) 2019\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR untech <edvbot@gmail.com>, 2019.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-04 12:57+0100\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: Edvard Botten <edvbot@gmail.com>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: norwegian\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=CHARSET\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hei, jeg er Pwnagotchi! Starter ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"En ny dag, ny jakt, og nye pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hack planeten!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI klart.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Det nevrale nettverket er klart.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Generer nøkkler, ikke skru meg av ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hei, kanalen {channel} er åpen! AP-en din takker.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Leser forrige sesjonen's logs ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Har lest {lines_so_far} linjer hittil ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Kjeder meg ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"La oss stikke på tur!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Dette er den beste dagen i mitt liv!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Jævlig dag :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Kjeder livet av meg ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Jeg er veldig trist ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Jeg er trist ...\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"La meg være alene ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Jeg er sint på deg!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Lever livet, lett!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Jeg pwner derfor er jeg.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Så mange nettverk!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Jeg har det så gøy!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Nysgjerrighet er min eneste forbrytelse ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Hallo {name}! Hyggelig å treffe deg!\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Yo {name}! Skjer'a?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Heisann {name} driver du med da?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"{name} er i nærheten!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... Ha det {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} er borte ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Oi da ... {name} forsvant.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} bommet!\"\n\nmsgid \"Missed!\"\nmsgstr \"Bommet!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Gode venner er livet verdt!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Jeg digger vennene mine!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Ingen vil leke med meg ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Jeg er så ensom ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Hvor er alle sammen?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Sover i {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\nmsgid \"Good night.\"\nmsgstr \"God natt.\"\n\nmsgid \"Zzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Venter i {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Ser meg rundt ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hei {what} la oss være venner!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Tilkobler til {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Bestemte meg att {mac} ikke lenger trenger WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Kobler av {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickbanner {mac}\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Fett, vi fikk {num} nye håndtrykk!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Du har {count} melding{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Oi, noe gikk helt skakk ... Rebooter ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Kicket {num} stasjoner\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Møtte {num} nye venner\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Skaffet {num} håndtrykk\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Møtte 1 annen\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Møtte {num} andre\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"Jeg har pwnet for {duration} og kicket {dauthed} klienter! Jeg har også \"\n\"møtt {associated} nye venner og spiste {handshakes} håndtrykk! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"timer\"\n\nmsgid \"minutes\"\nmsgstr \"minutter\"\n\nmsgid \"seconds\"\nmsgstr \"sekunder\"\n\nmsgid \"hour\"\nmsgstr \"time\"\n\nmsgid \"minute\"\nmsgstr \"minutt\"\n\nmsgid \"second\"\nmsgstr \"sekund\"\n"
  },
  {
    "path": "pwnagotchi/locale/pl/LC_MESSAGES/voice.po",
    "content": "# Polish voice data for pwnagotchi.\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# szymex73 <szymex73@gmail.com>, 2019.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.1.0\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-04 06:37+0100\\n\"\n\"PO-Revision-Date: 2019-10-21 10:55+0200\\n\"\n\"Last-Translator: gkrs <457603+gkrs@users.noreply.github.com>\\n\"\n\"Language-Team: PL <457603+gkrs@users.noreply.github.com>\\n\"\n\"Language: polish\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hej, jestem Pwnagotchi! Uruchamianie ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nowy dzień, nowe łowy, nowe pwny!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hakujmy planetę!\"\n\nmsgid \"AI ready.\"\nmsgstr \"SI gotowa.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Sieć neuronowa jest gotowa.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Generuję klucze, nie wyłączaj ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hej, kanał {channel} jest wolny! Twój AP będzie Ci wdzięczny.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Czytam logi z ostatniej sesji ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Na razie przeczytałem {lines_so_far} linii logów ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Nudzi mi się ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Chodźmy na spacer!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"To najlepszy dzień mojego życia!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Gówniany dzień :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Straaaasznie się nudzę ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Jest mi bardzo smutno ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Jest mi smutno\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Zostaw mnie w spokoju ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Wkurzam się na ciebie\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Cieszę się życiem!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Pwnuję więc jestem.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Jak dużo sieci!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Ale jest super!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Moją zbrodnią jest ciekawość ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Cześć {name}! Miło Cię poznać.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Siema {name}! Co słychać?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Hej {name} jak się masz?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Urządzenie {name} jest w pobliżu!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Umm ... żegnaj {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} zniknął ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Ups ... {name} zniknął.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} pudło!\"\n\nmsgid \"Missed!\"\nmsgstr \"Pudło!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Dobrzy przyjaciele to błogosławieństwo!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Kocham moich przyjaciół!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nikt nie chce się ze mną bawić ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Czuję się taki samotny ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Gdzie są wszyscy?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Zdrzemnę się przez {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\nmsgid \"Good night.\"\nmsgstr \"Dobranoc.\"\n\nmsgid \"Zzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Czekam {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Rozglądam się ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hej {what} zostańmy przyjaciółmi!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Dołączam do {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Siema {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Według mnie {mac} nie potrzebuje WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Rozłączam {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Banuję {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Super, zdobyliśmy {num} nowych handshake'ów!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Masz {count} nowych wiadomości!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ups, coś poszło nie tak ... Restaruję ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Wyrzuciłem {num} stacji\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Zdobyłem {num} nowych przyjaciół\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Zdobyłem {num} handshake'ów\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Spotkałem 1 kolegę\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Spotkałem {num} kolegów\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Pwnowałem {duration} i wyrzuciłem {deauthed} klientów! Spotkałem także \"\n\"{associated} nowych przyjaciół i zjadłem {handshakes} handshake'ow! \"\n\"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"godzin\"\n\nmsgid \"minutes\"\nmsgstr \"minut\"\n\nmsgid \"seconds\"\nmsgstr \"sekund\"\n\nmsgid \"hour\"\nmsgstr \"godzina\"\n\nmsgid \"minute\"\nmsgstr \"minuta\"\n\nmsgid \"second\"\nmsgstr \"sekunda\"\n"
  },
  {
    "path": "pwnagotchi/locale/pt/LC_MESSAGES/voice.po",
    "content": "# pwnagotchi Portuguese (european) translation file.\n# Copyright (C) 2019 David Sopas\n# This file is distributed under the same license as the PACKAGE package.\n# David Sopas <email@aleatorio.xyz>, 2019.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-09 17:42+0200\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: David Sopas <email@aleatorio.xyz>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: Portuguese\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=CHARSET\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Olá, eu sou o Pwnagotchi! A iniciar ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Novo dia, nova caçada, novos pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hacka o Planeta!\"\n\nmsgid \"AI ready.\"\nmsgstr \"IA pronta.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"A rede neural está pronta.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, o canal {channel} está livre! O teu AP irá agradecer.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Estou aborrecido ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Vamos fazer uma caminhada!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Este é o melhor dia da minha vida!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Que merda de dia :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Estou muito aborrecido ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Estou muito triste ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Estou triste\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Estou aproveitar a vida!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Eu pwn, logo existo.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Tantas redes!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Estou a divertir-me tanto!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"O meu crime é ser curioso ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Olá {name}! Prazer em conhecer-te. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"A unidade {name} está perto! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... adeus {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} desapareceu ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Ups ... {name} desaparecey.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} perdido!\"\n\nmsgid \"Missed!\"\nmsgstr \"Perdido!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Ninguém quer brincar comigo ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Sinto-me tão só ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Onde estão todos?\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"A fazer uma sesta durante {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Boa noite.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"A aguardar durante {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"A dar uma olhada ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what} vamos ser amigos!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"A associar a {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Decidi que o {mac} não precisa de WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"A fazer deauth {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"A chutar {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Porreiro, temos {num} novo handshake{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ups, algo correu mal ... A reiniciar ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Chutei {num} estações\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Fiz {num} novos amigos\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Obti {num} handshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Conheci 1 peer\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Conheci {num} peers\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"Tenho estado a pwnar durante {duration} e chutei {deauthed} clientes! Também conheci \"\n\"{associated} novos amigos e comi {handshakes} handshakes! #pwnagotchu \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"horas\"\n\nmsgid \"minutes\"\nmsgstr \"minutos\"\n\nmsgid \"seconds\"\nmsgstr \"segundos\"\n\nmsgid \"hour\"\nmsgstr \"hora\"\n\nmsgid \"minute\"\nmsgstr \"minuto\"\n\nmsgid \"second\"\nmsgstr \"segundo\"\n"
  },
  {
    "path": "pwnagotchi/locale/pt-BR/LC_MESSAGES/voice.po",
    "content": "# pwnagotchi Brazilian Portuguese translation file.\n# Copyright (C) 2019 Cassiano Aquino\n# This file is distributed under the same license as the pwnagotchi package.\n# Cassiano Aquino <cassianoaquino@me.com>, 2019.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-05 14:10+0200\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: Cassiano Aquino <cassianoaquino@me.com>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: Brazilian Portuguese\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Oi! Eu sou o Pwnagotchi! Iniciando ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Novo dia, Nova caça, Novos pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hackeie o Planeta!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI pronta.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"A rede neural está pronta.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Ei, o canal {channel} está livre! Seu AP ira agradecer.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Estou entediado ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Vamos dar uma caminhada!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Este e o melhor dia da minha vida!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Dia de merda :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Estou extremamente entediado ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Estou muito triste ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Estou triste\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Estou aproveitando a vida!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"pwn, logo existo.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Quantas redes!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Estou me divertindo muito!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Meu crime é ser curioso ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Olá {name}! Prazer em conhecê-lo. {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"Unidade {name} está próxima! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... até logo {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} desapareceu ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Oops ... {name} desapareceu.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} perdido!\"\n\nmsgid \"Missed!\"\nmsgstr \"Perdido!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Ninguém quer brincar comigo ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Estou tão sozinho ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Aonde está todo mundo?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Cochilando por {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Aguardando por {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Olhando ao redor ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Ei {what} vamos ser amigos!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Associando com {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Oi {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Acabei de decidir que {mac} não precisa de WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"De-autenticando {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickbanning {mac}\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Legal, nos capturamos {num} handshake{plural} novo{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ops, algo falhou ... Reiniciando ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Kickei {num} estações\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Fiz {num} novos amigos\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Peguei {num} handshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Conheci 1 peer\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Conheci {num} peers\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Eu estou pwning fazem {duration} e kickei {deauthed} clientes! Eu também conheci \"\n\"{associated} novos amigos e comi {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"horas\"\n\nmsgid \"minutes\"\nmsgstr \"minutos\"\n\nmsgid \"seconds\"\nmsgstr \"segundos\"\n\nmsgid \"hour\"\nmsgstr \"hora\"\n\nmsgid \"minute\"\nmsgstr \"minuto\"\n\nmsgid \"second\"\nmsgstr \"segundo\"\n"
  },
  {
    "path": "pwnagotchi/locale/ro/LC_MESSAGES/voice.po",
    "content": "# Pwnagotchi translation.\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR <radu.ungureanu@techie.com>, 2019.\n#\n#,\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-04 12:57+0100\\n\"\n\"PO-Revision-Date: 2019-11-20 00:18+594\\n\"\n\"Last-Translator: Ungureanu Radu-Andrei <radu.ungureanu@techie.com>\\n\"\n\"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.\"\n\"com>\\n\"\n\"Language: ro\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Buna, sunt Pwnagotchi! Pornesc...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"O noua zi, o noua vanatoare, noi pwn-uri!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Pirateaza planeta!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI-ul e gata.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Rețeaua neuronală este gata.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Se generează chei, nu închide...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, canalul {channel} este liber! AP-ul tău îti va mulțumi.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Se citesc log-urile din sesiunea anterioara...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Am citit {lines_so_far} linii din log pana acum...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Sunt plictisit...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Hai să ne plimbăm!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Asta este cea mai buna zi din viața mea!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"O zi proasta :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Sunt extrem de plictisit...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Sunt foarte trist...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Sunt trist\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Lasă-mă in pace...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Sunt supărat pe tine!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Trăiesc viața!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Eu pwn-ez, deci aici sunt.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Atât de multe rețele!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Mă distrez așa de mult!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Crima mea este una de curiozitate...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Bună {name}! Mă bucur să te cunosc.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Yo {name}! Cmf?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Hey {nume} ce mai faci?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Unitatea {name} este aproape!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm... Pa {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} a dispărut.\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Oops... {name} a dispărut.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} ratat!\"\n\nmsgid \"Missed!\"\nmsgstr \"Ratat!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Prietenii buni sunt o binecuvântare!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Îmi iubesc prietenii!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nimeni nu vrea sa se joace cu mine...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Mă simt așa de singuratic...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Unde-i toată lumea?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Dorm pentru {secs}s...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Noapte bună.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Aștept pentru {secs}s...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Mă uit împrejur ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what} hai să fim prieteni!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Mă asociez cu {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what}\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Am decis că lui {mac} nu-i trebuie WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Îl deautentific pe {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Îi dau kickban lui {mac}\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Șmecher, avem {num} de handshake-uri noi!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Ai {count} mesaj(e) nou/noi!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"OOps, ceva s-a întamplat... Îmi dau reboot...+\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Am dat afară {num} de stații\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Am făcut {num} prieteni noi \\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Am primit {num} de handshake-uri\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Am întalnit un peer\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Am întalnit {num} de peer-uri\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"Eu am făcut pwning pentru {duration} și am dat afara {deauthed} clienți! \"\n\"De asemenea, am întalnit {associated} prieteni noi și am mancat {handshakes} de \"\n\"handshake-uri! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"ore\"\n\nmsgid \"minutes\"\nmsgstr \"minute\"\n\nmsgid \"seconds\"\nmsgstr \"secunde\"\n\nmsgid \"hour\"\nmsgstr \"oră\"\n\nmsgid \"minute\"\nmsgstr \"minut\"\n\nmsgid \"second\"\nmsgstr \"secundă\"\n"
  },
  {
    "path": "pwnagotchi/locale/ru/LC_MESSAGES/voice.po",
    "content": "# Pwnagotchi Russian translation.\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# FIRST AUTHOR <25989971+adolfaka@users.noreply.github.com>, 2019.\n# Second author <https://github.com/mbgroot>, 2019\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: Pwnagotchi Russian translation v 0.0.2\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n\"\n\"%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Language-Team: \\n\"\n\"MIME-Version: 1.0\\n\"\n\"Language: ru\\n\"\n\"X-Generator: Poedit 2.2.4\\n\"\n\"X-Poedit-SourceCharset: UTF-8\\n\"\n\"X-Poedit-Basepath: .\\n\"\n\"X-Poedit-SearchPath-0: voice.po\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"Хрррр...\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Привет, я Pwnagotchi! Стартуем!\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Новый день, новая охота, новые взломы!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Взломай эту Планету!\"\n\nmsgid \"AI ready.\"\nmsgstr \"A.I. готов.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Нейронная сеть готова.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Генерация ключей, не выключайте...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Эй, канал {channel} свободен! Ваша точка доступа скажет спасибо.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Чтение логов последнего сеанса...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Чтение {lines_so_far} строк журнала...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Мне скучно …\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Пойдем прогуляемся!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Лучший день в моей жизни!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Дерьмовый день :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Мне очень скучно …\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Мне очень грустно …\"\n\nmsgid \"I'm sad\"\nmsgstr \"Мне грустно\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Оставь меня в покое...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Я зол на тебя!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Живу полной жизнью!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Я взламываю, поэтому я существую.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Так много сетей!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Мне так весело!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Моё преступление - это любопытство…\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Привет, {name}! Рад встрече с тобой!\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"Цель {name} близко!\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Хэй {name}! Как дела?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Цель {name} рядом!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Хм … до свидания {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} ушла…\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Упс… {name} исчезла.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} упустил!\"\n\nmsgid \"Missed!\"\nmsgstr \"Промахнулся!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Хорошие друзья - это благословение!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Я люблю своих друзей!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Никто не хочет со мной играть ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Я так одинок…\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Где все?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Дремлет {secs}с …\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Хррр...\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"Хррррр.. ({secs}c)\"\n\nmsgid \"Good night.\"\nmsgstr \"Доброй ночи.\"\n\nmsgid \"Zzz\"\nmsgstr \"Хрррр\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Ждем {secs}c …\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Осматриваюсь вокруг ({secs}с)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Эй, {what} давай дружить!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Связываюсь с {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Йоy {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Просто решил, что {mac} не нужен WiFi! Кхе-кхе)\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Деаутентификация {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Кикаю {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Круто, мы получили {num} новое рукопожатие!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ой, что-то пошло не так … Перезагружаюсь …\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Кикнул {num} станцию\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Заимел {num} новых друзей\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Получил {num} рукопожатий\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Встретился один знакомый\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Встретились {num} приятелей\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Я взламывал {duration} и кикнул {deauthed} клиентов! Я также встретил \"\n\"{associated} новых друзей и съел {handshakes} рукопожатий! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"часов\"\n\nmsgid \"hour\"\nmsgstr \"час\"\n\nmsgid \"minutes\"\nmsgstr \"минут\"\n\nmsgid \"minute\"\nmsgstr \"минуту\"\n"
  },
  {
    "path": "pwnagotchi/locale/se/LC_MESSAGES/voice.po",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-03 16:47+0200\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: Mike Eriksson <mike@swedishmike.org>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: swedish\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hej, jag är Pwnagotchi! Startar ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Ny dag, ny jakt, nya pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hacka planeten!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI klar.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Det neurala nätverket är klart.\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Du, kanal {channel} är ledig! Din AP will gilla detta.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Jag har det så tråkigt...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Dags för en promenad!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Det här är den bästa dagen i mitt liv!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Idag suger :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Jag är extremt uttråkad ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Jag är jätteledsen ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Jag är ledsen\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Nu leker livet!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Jag pwnar därför är jag.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Så många nätverk!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Fan vad skoj jag har!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Mitt brott är att vara nyfiken ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you. {name}\"\nmsgstr \"Hejsan {name}! Trevligt att träffas {name}\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby! {name}\"\nmsgstr \"Enheten {name} är nära! {name}\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... farväl {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} är borta ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Hoppsan ... {name} är borta.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} missade!\"\n\nmsgid \"Missed!\"\nmsgstr \"Bom!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Ingen vill leka med mig ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Jag är så ensam ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Var är alla?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Sover för {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Väntar {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Tittar omkring mig ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hejsan {what} låt oss vara vänner\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Ansluter till {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Jag bestämde just att {mac} inte behöver WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Lysande, vi har {num} ny handskakningar{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Hoppsan, någpt gick fel ... Startar om ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Sparkade {num} stationer\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Har {num} nya vänner\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Har {num} handskakningar\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Mötte 1 jämlike\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Mötte {num} jämlikar\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"Jag har pwnat för {duration} och sparkat ut {deauthed} klienter, Jag \"\n\"har också träffat {associated} nya vänner och har skakat {handshakes} händer! \"\n\"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"timmar\"\n\nmsgid \"hour\"\nmsgstr \"timme\"\n\nmsgid \"minutes\"\nmsgstr \"minuter\"\n\nmsgid \"minute\"\nmsgstr \"minut\"\n"
  },
  {
    "path": "pwnagotchi/locale/sk/LC_MESSAGES/voice.po",
    "content": "# Slovak language\n# Copyright (C) 2019\n# This file is distributed under the same license as the pwnagotchi package.\n# mil1200 <mil.kyselica@gmail.com>, 2019.\n#\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-8 17:55+0200\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: Milan Kyselica <mil.kyselica@gmail.com>\\n\"\n\"Language-Team: SK\\n\"\n\"Language: sk\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Ahoj, ja som Pwnagotchi! Začíname ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Nový deň, nový lov, nové pwns!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hacknime Planétu!\"\n\nmsgid \"AI ready.\"\nmsgstr \"AI pripravené.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Neurónová sieť je pripravená.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Generujú sa kľúče, nevypínaj ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hej, kanál {channel} je voľný! Váš AP vám poďakuje.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Nudím sa ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Poďme na prechádzku!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Toto je najlepší deň môjho života!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Na hovno deň :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Veľmi sa nudím ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Som veľmi smutný ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Som smutný\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Žijem život!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"I pwn therefore I am.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Toľko sietí !!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Zabávam sa!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Môj zločin je zvedavosť ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Dobrý deň, {name}! Rád som ťa spoznal.\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Jednotka {name} je blízko!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... zbohom {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} je preč ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Hups ... {name} je preč.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} nechytené!\"\n\nmsgid \"Missed!\"\nmsgstr \"Vedľa!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Dobrí priatelia sú požehnaním!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Milujem svojich priateľov!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nikto sa so mnou nechce hrať ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Cítim sa tak sám ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Kde sú všetci ?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Zdriemnem si na {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s)\"\n\nmsgid \"Good night.\"\nmsgstr \"Dobrú noc.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Čaká sa {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Rozhliadam sa okolo ({secs} s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Ahoj {what} buďme priatelia!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Spájam sa s {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Rozhodol som sa že {mac} nepotrebuje Wi-Fi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Deautentifikujem {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Kickujem {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Super, máme {num} nový handshake{plural}!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Máte {count} novú správu{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ops, niečo sa pokazilo ... Reštartujem sa ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Kicknutá/ých {num} stanica/íc\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Získaní {num} noví kamaráti\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Získali sme {num} handshake/-y/ov rúk\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Sretli sme 1 rovesníka\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Stretli sme {num} rovesníkov\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"Pwnoval som {duration} a kickol som {deauthed} klienta/ov! Tiež som\"\n\"stretol {associated} nového/ých kamaráta/ov a zjedol {handshakes} handshake/y!\"\n\" #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"hodiny\"\n\nmsgid \"minutes\"\nmsgstr \"minúty\"\n\nmsgid \"seconds\"\nmsgstr \"sekundy\"\n\nmsgid \"hour\"\nmsgstr \"hodina\"\n\nmsgid \"minute\"\nmsgstr \"minúta\"\n\nmsgid \"second\"\nmsgstr \"sekunda\"\n"
  },
  {
    "path": "pwnagotchi/locale/spa/LC_MESSAGES/voice.po",
    "content": "# Interfaz en español para pwnagotchi\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# Angel Hernandez Segura, 2019.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-04 12:57+0100\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: Angel Hernandez Segura <ahsec.7@gmail.com>\\n\"\n\"Language-Team: Español <LL@li.org>\\n\"\n\"Language: \\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=CHARSET\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Hola, Soy Pwnagotchi! Iniciando...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Un nuevo dia, nuevos objetivos, nuevos pwns\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Hack the Planet!\"\n\nmsgid \"AI ready.\"\nmsgstr \"IA lista\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"La red neuronal esta lista\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Generando llaves, no apagar\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, canal {channel} esta libre! Tu AP te lo agredecera\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Leyendo logs de la ultima sesion\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"He leido {lines_so_far} lineas de los logs hasta ahora \"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Estoy aburrido\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Vamos a caminar!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Este es el mejor dia de mi vida\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Dia de mierda :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Estoy extremadamente aburrido ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Estoy mut triste\"\n\nmsgid \"I'm sad\"\nmsgstr \"Estoy triste\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Dejame solo ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Estoy enojado contigo!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Estoy disfrutando la vida!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Yo pwn, por lo tanto existo\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Tantas redes!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Me estoy divirtiendo mucho!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Mi crimen es la curiosidad ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Hola {name}! Mucho gusto.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"Yo {name}! Que hay?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Hey {name} como te va?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Unit {name} esta cerca!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Uhm ... adios {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} se fue ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Whoops ... {name} se fue\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} se ha perdido!\"\n\nmsgid \"Missed!\"\nmsgstr \"Perdido!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Los buenos amigos son una bendicion\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Amo a mis amigos!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Nadie quiere jugar conmigo ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Me siento muy solo ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Donde estan todos?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Tomando una siesta por {secs}s ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}s) \"\n\nmsgid \"Good night.\"\nmsgstr \"Buenas noches.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Esperando por {secs}s ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Mirando alrededor ({secs}s)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Hey {what} vamos a ser amigos!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Asociandose a {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Yo {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Acabo de decidir que {mac} no necesita WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"De-autenticando {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Vetando {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Bien, obtuvimos {num} nuevos handshake{plural}!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Tienes {count} nuevos mensajes{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Oops, algo salio mal ... Reiniciando ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Bloquee {num} staciones\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Hice {num} nuevos amigos\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Obtuve {num} handshakes\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Conoci a 1 unidad\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"conoci {num} unidades\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"He estado hackeando por {duration} y de-autenticando {deauthed} \"\n\"clientes! Tambien conoci {associated} nuevos amigos y comi {handshakes} \"\n\"handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"horas\"\n\nmsgid \"minutes\"\nmsgstr \"minutos\"\n\nmsgid \"seconds\"\nmsgstr \"segundos\"\n\nmsgid \"hour\"\nmsgstr \"hora\"\n\nmsgid \"minute\"\nmsgstr \"minuto\"\n\nmsgid \"second\"\nmsgstr \"segundo\"\n"
  },
  {
    "path": "pwnagotchi/locale/tr/LC_MESSAGES/voice.po",
    "content": "# Pwnagotchi Turkish translation.\n# Copyright (C) 2021\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR <abtonc@icloud.com>, 2021.\n#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-29 21:50+0100\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: Arda Barış Tonç <abtonc@icloud.com>\\n\"\n\"Language-Team: \\n\"\n\"Language: Turkish\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZzzZzZZzzzzZ\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Merhaba, ben Pwnagotchi! Başlatılıyorum ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Yeni bir gün, yeni bir av, yeni pwn'lar!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Dünyayı Hackle!\"\n\nmsgid \"AI ready.\"\nmsgstr \"Yapay zeka hazır.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Nöral ağ hazır.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Anahatarlar oluşturuluyor, lütfen kapatmayın ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Hey, {channel} kanalı boş! AP'niz teşekkür edecek.\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"Son oturum kayıtları okunuyor ...\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"Şimdiye kadar {lines_so_far} kayıt satırı okundu ...\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Sıkıldım ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Yürüyüşe çıkalım!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Bugün hayatımın en iyi günü!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Bok gibi bir gün :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Çook sıkıldım ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Çok mutsuzum ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Mutsuzum\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"Beni yalnız bırak ...\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"Sana kızgınım!\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Bu hayatı yaşıyorum!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Ben, pwn'ladığım için benim.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Çok fazla ağ var!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Çok eğleniyorum!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Tek suçum merak etmek ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Merhaba {name}! Tanıştığıma memnun oldum.\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"{name}, kanka! Naber?\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"Nasılsın {name}?\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"{name} birimi yakında!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"ııı ... görüşürüz {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} gitti.\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Hoppala ... {name} gitti.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name}'i kaçırdık ya!\"\n\nmsgid \"Missed!\"\nmsgstr \"Kaçırdık!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"İyi arkadaşlar nimettir!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Arkadaşlarımı seviyorum!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Hiç kimse benimle birlikte oynamak istemiyor ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Çok yalnız hissediyorum ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Herkes nerede!?\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"{secs}dir kestiriyorum ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"ZzzzZz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzZ ({secs})\"\n\nmsgid \"Good night.\"\nmsgstr \"İyi geceler.\"\n\nmsgid \"Zzz\"\nmsgstr \"ZzZ\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"{secs}dir bekleniyor ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Etrafa bakıyorum ({secs})\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Arkadaş olalım {what}!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"{what} ile tanışıyoruz\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Hey {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Sanırım {mac}'in WiFi'a ihtiyacı yok!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"{mac} ağdan çıkarılıyor\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"{mac} atılıp yasaklanıyor!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Güzel, yeni {num} el sıkıştık!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"{count} Tane yeni mesajınız var!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Haydaa, bir şeyler ters gitti ... Yeniden başlatılıyor ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"{num} İstasyon atıldı\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"{num} Yeni arkadaş edindim\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"{num} El sıkıştım\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"1 Kişiyle tanıştım\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"{num} Kişiyle tanıştım\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"{duration}'dır pwn'lıyorum ve {deauthed} kişiyi attım. Hem de {associated}\"\n\"yeni kişiyle tanıştım ve {handshakes} el sıkıştım! #pwnagotchi \"\n\"#pwnlog #pwnyaşam #dünyayıhackle #skynet\"\n\nmsgid \"hours\"\nmsgstr \"saat\"\n\nmsgid \"minutes\"\nmsgstr \"dakika\"\n\nmsgid \"seconds\"\nmsgstr \"saniye\"\n\nmsgid \"hour\"\nmsgstr \"saat\"\n\nmsgid \"minute\"\nmsgstr \"dakika\"\n\nmsgid \"second\"\nmsgstr \"saniye\"\n\n#, python-brace-format\nmsgid \"Uploading data to {to} ...\"\nmsgstr \"{to}'ye veri yükleniyor ...\"\n"
  },
  {
    "path": "pwnagotchi/locale/tw/LC_MESSAGES/voice.po",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR <shark_shaking@hotmail.com>, 2020.\n# 有很多翻譯不到味，如果有繁體愛好者，歡迎之後大家一起翻譯！\n\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2020-10-21 15:56+0200\\n\"\n\"PO-Revision-Date: 2020-10-22 10:00+0008\\n\"\n\"Last-Translator: ShaqKSmith <shark_shaking@hotmail.com>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: traditional chinese\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"HI!我是Pwnagotchi!\\n程式啟動...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"新的一天!\\n新的狩獵!新的入侵!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"我要駭入\\n地球的所有人!\"\n\nmsgid \"AI ready.\"\nmsgstr \"人工智慧已啟動.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"神經網路已啟動.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"產生金鑰中,\\n請勿關閉...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"嘿,{channel}很順暢!\\n你的WIFI會感謝你的.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"我好無聊...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"我們出去走走吧!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"這是我生命中最美好的一天!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"糟糕的一天 :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"我超無聊的...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"我好難過...\"\n\nmsgid \"I'm sad\"\nmsgstr \"傷心。\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"真是充實的一生!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"我駭故我在.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"好多網路啊！！！\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"我玩的超級開心!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"我的缺點就是\\n太好奇了...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Hello{name}!\\n很高興認識你.\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"{name}\\n就在附近!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"啊 ... \\n拜拜{name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name}\\n不見了 ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"歐哦...\\n{name}\\n不見了.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"我剛剛錯過了{name}!\"\n\nmsgid \"Missed!\"\nmsgstr \"又錯過了!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"有個好朋友\\n真幸福!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"我喜歡\\n我的朋友!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"沒人想跟我玩...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"我感覺好孤單...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"大家都去哪裡了?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"我想瞇{secs}秒一下...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz({secs}秒)\"\n\nmsgid \"Good night.\"\nmsgstr \"晚安.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"等我{secs}秒...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"環顧四周({secs}秒)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"嗨\\n{what}\\n讓我我們來當朋友吧!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"正在連接\\n{what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"喲,\\n{what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"我要讓\\n{mac}\\n斷線!\\n他不需要上網!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"解除\\n{mac}\\n的授權中\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"把\\n{mac}\\n踢出中!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"酷哦,我們抓到{num}個\\n新的握手包{plural}!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"你有{count}個新訊息{plural}!\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"喔歐,有些地方出錯了...\\n重新啟動中...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"踢了 {num} 個設備\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"交了 {num} 個新朋友\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"捕獲了 {num} 個握手包\\n\"\n\nmsgid \"Met 1 peer 同好\"\nmsgstr \"遇到了 １ 個\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"遇到了 {num} 個同好\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"我花了{duration}的時間\\n駭入和踢了{deauthed}好多設備.\\n\"\n\"我還交了好多{associated}新朋友,\\n而且抓到了{handshakes}握手包!\"\n\"#pwnagotchi#入侵日志 #駭客人生 #入侵整個星球 #天網\"\n\nmsgid \"hours\"\nmsgstr \"時\"\n\nmsgid \"minutes\"\nmsgstr \"分\"\n\nmsgid \"seconds\"\nmsgstr \"秒\"\n\nmsgid \"hour\"\nmsgstr \"時\"\n\nmsgid \"minute\"\nmsgstr \"分\"\n\nmsgid \"second\"\nmsgstr \"秒\"\n"
  },
  {
    "path": "pwnagotchi/locale/ua/LC_MESSAGES/voice.po",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# damoklov <mishanya@protonmail.com>, 2019.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-10-23 20:56+0200\\n\"\n\"PO-Revision-Date: 2019-11-02 16:20+0200\\n\"\n\"Last-Translator: damoklov <mishanya@protonmail.com>\\n\"\n\"Language-Team: Ukrainian\\n\"\n\"Language: ua\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=utf-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"ZzzzZZzzzzZzzz\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"Привіт, я Pwnagotchi! Починаймо ...\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"Новий день, нове полювання, нові проникнення!\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"Хакни цілу планету!\"\n\nmsgid \"AI ready.\"\nmsgstr \"Штучний інтелект готовий.\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"Нейронна мережа готова.\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"Генерую ключі, не вимикай живлення ...\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"Агов, канал {channel} вільний! Ваша точка доступу буде вдячна.\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"Мені сумно ...\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"Нумо прогуляймось!\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"Сьогодні найкращий день у моєму житті!\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"Поганенький день :/\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"Мені геть сумно ...\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"Я дуже засмучений ...\"\n\nmsgid \"I'm sad\"\nmsgstr \"Я засмучений\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"Ось таке у мене життя!\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"Народжений, щоб зламувати.\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"Овва, стільки мереж!!!\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"Мені так весело!\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"Мій єдиний злочин - це допитливість ...\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"Привіт, {name}! Приємно познайомитись.\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"Ціль {name} неподалік!\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"Що ж ... бувай, {name}\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"{name} зникла ...\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"Ой-ой ... {name} зникла.\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"{name} втрачено!\"\n\nmsgid \"Missed!\"\nmsgstr \"Не впіймав!\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"Справжні друзі - це чудово!\"\n\nmsgid \"I love my friends!\"\nmsgstr \"Я люблю своїх друзів!\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"Ніхто не хоче бавитись зі мною ...\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"Я почуваюсь вкрай самотньо ...\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"Куди всі зникли?!\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"Дрімаю {secs}с ...\"\n\nmsgid \"Zzzzz\"\nmsgstr \"Zzzzz\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"ZzzZzzz ({secs}с)\"\n\nmsgid \"Good night.\"\nmsgstr \"Спокійної нічки.\"\n\nmsgid \"Zzz\"\nmsgstr \"Zzz\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"Очікую {secs}с ...\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"Роздивляюсь довкола ({secs}с)\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"Агов, {what}, будьмо друзями!\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"Налагоджую зв'язок з {what}\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"Гей, {what}!\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"Вирішив, що {mac} більше не потребує WiFi!\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"Від'єднюю {mac}\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"Вилучаю {mac}!\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"Отакої, у нас є {num} нових рукостискань!\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"Нових повідомлень: {count}\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"Ой, щось пішло не так ... Перезавантажуюсь ...\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"Від'єднав {num} станцій\\n\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"Нових друзів у мене: {num}\\n\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"Перехопив рукостискань: {num}\\n\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"Зустрівся з одним знайомим\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"Зустрівся з {num}-ма знайомими\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\"Я зламував впродовж {duration} та від'єднав {deauthed} клієнтів! Я зустрів \"\n\"{associated} нових друзів та схрумав {handshakes} рукостискань! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\n\nmsgid \"hours\"\nmsgstr \"годин\"\n\nmsgid \"minutes\"\nmsgstr \"хвилин\"\n\nmsgid \"seconds\"\nmsgstr \"секунд\"\n\nmsgid \"hour\"\nmsgstr \"година\"\n\nmsgid \"minute\"\nmsgstr \"хвилина\"\n\nmsgid \"second\"\nmsgstr \"секунда\"\n"
  },
  {
    "path": "pwnagotchi/locale/voice.pot",
    "content": "# SOME DESCRIPTIVE TITLE.\n# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER\n# This file is distributed under the same license as the PACKAGE package.\n# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n#\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: PACKAGE VERSION\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2019-11-29 21:50+0100\\n\"\n\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"\n\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n\"Language: \\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=CHARSET\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\nmsgid \"ZzzzZZzzzzZzzz\"\nmsgstr \"\"\n\nmsgid \"Hi, I'm Pwnagotchi! Starting ...\"\nmsgstr \"\"\n\nmsgid \"New day, new hunt, new pwns!\"\nmsgstr \"\"\n\nmsgid \"Hack the Planet!\"\nmsgstr \"\"\n\nmsgid \"AI ready.\"\nmsgstr \"\"\n\nmsgid \"The neural network is ready.\"\nmsgstr \"\"\n\nmsgid \"Generating keys, do not turn off ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Hey, channel {channel} is free! Your AP will say thanks.\"\nmsgstr \"\"\n\nmsgid \"Reading last session logs ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Read {lines_so_far} log lines so far ...\"\nmsgstr \"\"\n\nmsgid \"I'm bored ...\"\nmsgstr \"\"\n\nmsgid \"Let's go for a walk!\"\nmsgstr \"\"\n\nmsgid \"This is the best day of my life!\"\nmsgstr \"\"\n\nmsgid \"Shitty day :/\"\nmsgstr \"\"\n\nmsgid \"I'm extremely bored ...\"\nmsgstr \"\"\n\nmsgid \"I'm very sad ...\"\nmsgstr \"\"\n\nmsgid \"I'm sad\"\nmsgstr \"\"\n\nmsgid \"Leave me alone ...\"\nmsgstr \"\"\n\nmsgid \"I'm mad at you!\"\nmsgstr \"\"\n\nmsgid \"I'm living the life!\"\nmsgstr \"\"\n\nmsgid \"I pwn therefore I am.\"\nmsgstr \"\"\n\nmsgid \"So many networks!!!\"\nmsgstr \"\"\n\nmsgid \"I'm having so much fun!\"\nmsgstr \"\"\n\nmsgid \"My crime is that of curiosity ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Hello {name}! Nice to meet you.\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Yo {name}! Sup?\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Hey {name} how are you doing?\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Unit {name} is nearby!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Uhm ... goodbye {name}\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"{name} is gone ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Whoops ... {name} is gone.\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"{name} missed!\"\nmsgstr \"\"\n\nmsgid \"Missed!\"\nmsgstr \"\"\n\nmsgid \"Good friends are a blessing!\"\nmsgstr \"\"\n\nmsgid \"I love my friends!\"\nmsgstr \"\"\n\nmsgid \"Nobody wants to play with me ...\"\nmsgstr \"\"\n\nmsgid \"I feel so alone ...\"\nmsgstr \"\"\n\nmsgid \"Where's everybody?!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Napping for {secs}s ...\"\nmsgstr \"\"\n\nmsgid \"Zzzzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"ZzzZzzz ({secs}s)\"\nmsgstr \"\"\n\nmsgid \"Good night.\"\nmsgstr \"\"\n\nmsgid \"Zzz\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Waiting for {secs}s ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Looking around ({secs}s)\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Hey {what} let's be friends!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Associating to {what}\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Yo {what}!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Just decided that {mac} needs no WiFi!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Deauthenticating {mac}\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Kickbanning {mac}!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Cool, we got {num} new handshake{plural}!\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"You have {count} new message{plural}!\"\nmsgstr \"\"\n\nmsgid \"Oops, something went wrong ... Rebooting ...\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Kicked {num} stations\\n\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Made {num} new friends\\n\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Got {num} handshakes\\n\"\nmsgstr \"\"\n\nmsgid \"Met 1 peer\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Met {num} peers\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"\"\n\"I've been pwning for {duration} and kicked {deauthed} clients! I've also met \"\n\"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi \"\n\"#pwnlog #pwnlife #hacktheplanet #skynet\"\nmsgstr \"\"\n\nmsgid \"hours\"\nmsgstr \"\"\n\nmsgid \"minutes\"\nmsgstr \"\"\n\nmsgid \"seconds\"\nmsgstr \"\"\n\nmsgid \"hour\"\nmsgstr \"\"\n\nmsgid \"minute\"\nmsgstr \"\"\n\nmsgid \"second\"\nmsgstr \"\"\n\n#, python-brace-format\nmsgid \"Uploading data to {to} ...\"\nmsgstr \"\"\n"
  },
  {
    "path": "pwnagotchi/log.py",
    "content": "import hashlib\nimport time\nimport re\nimport os\nimport logging\nimport shutil\nimport gzip\nimport warnings\nfrom datetime import datetime\n\nfrom pwnagotchi.voice import Voice\nfrom pwnagotchi.mesh.peer import Peer\nfrom file_read_backwards import FileReadBackwards\n\nLAST_SESSION_FILE = '/root/.pwnagotchi-last-session'\n\n\nclass LastSession(object):\n    EPOCH_TOKEN = '[epoch '\n    EPOCH_PARSER = re.compile(r'^.+\\[epoch (\\d+)\\] (.+)')\n    EPOCH_DATA_PARSER = re.compile(r'([a-z_]+)=([^\\s]+)')\n    TRAINING_TOKEN = ' training epoch '\n    START_TOKEN = 'connecting to http'\n    DEAUTH_TOKEN = 'deauthing '\n    ASSOC_TOKEN = 'sending association frame to '\n    HANDSHAKE_TOKEN = '!!! captured new handshake '\n    PEER_TOKEN = 'detected unit '\n\n    def __init__(self, config):\n        self.config = config\n        self.voice = Voice(lang=config['main']['lang'])\n        self.path = config['main']['log']['path']\n        self.last_session = []\n        self.last_session_id = ''\n        self.last_saved_session_id = ''\n        self.duration = ''\n        self.duration_human = ''\n        self.deauthed = 0\n        self.associated = 0\n        self.handshakes = 0\n        self.peers = 0\n        self.last_peer = None\n        self.epochs = 0\n        self.train_epochs = 0\n        self.min_reward = 1000\n        self.max_reward = -1000\n        self.avg_reward = 0\n        self._peer_parser = re.compile(\n            'detected unit (.+)@(.+) \\(v.+\\) on channel \\d+ \\(([\\d\\-]+) dBm\\) \\[sid:(.+) pwnd_tot:(\\d+) uptime:(\\d+)\\]')\n        self.parsed = False\n\n    def _get_last_saved_session_id(self):\n        saved = ''\n        try:\n            with open(LAST_SESSION_FILE, 'rt') as fp:\n                saved = fp.read().strip()\n        except:\n            saved = ''\n        return saved\n\n    def save_session_id(self):\n        with open(LAST_SESSION_FILE, 'w+t') as fp:\n            fp.write(self.last_session_id)\n            self.last_saved_session_id = self.last_session_id\n\n    def _parse_datetime(self, dt):\n        dt = dt.split('.')[0]\n        dt = dt.split(',')[0]\n        dt = datetime.strptime(dt.split('.')[0], '%Y-%m-%d %H:%M:%S')\n        return time.mktime(dt.timetuple())\n\n    def _parse_stats(self):\n        self.duration = ''\n        self.duration_human = ''\n        self.deauthed = 0\n        self.associated = 0\n        self.handshakes = 0\n        self.epochs = 0\n        self.train_epochs = 0\n        self.peers = 0\n        self.last_peer = None\n        self.min_reward = 1000\n        self.max_reward = -1000\n        self.avg_reward = 0\n\n        started_at = None\n        stopped_at = None\n        cache = {}\n\n        for line in self.last_session:\n            parts = line.split(']')\n            if len(parts) < 2:\n                continue\n\n            try:\n                line_timestamp = parts[0].strip('[')\n                line = ']'.join(parts[1:])\n                stopped_at = self._parse_datetime(line_timestamp)\n                if started_at is None:\n                    started_at = stopped_at\n\n                if LastSession.DEAUTH_TOKEN in line and line not in cache:\n                    self.deauthed += 1\n                    cache[line] = 1\n\n                elif LastSession.ASSOC_TOKEN in line and line not in cache:\n                    self.associated += 1\n                    cache[line] = 1\n\n                elif LastSession.HANDSHAKE_TOKEN in line and line not in cache:\n                    self.handshakes += 1\n                    cache[line] = 1\n\n                elif LastSession.TRAINING_TOKEN in line:\n                    self.train_epochs += 1\n\n                elif LastSession.EPOCH_TOKEN in line:\n                    self.epochs += 1\n                    m = LastSession.EPOCH_PARSER.findall(line)\n                    if m:\n                        epoch_num, epoch_data = m[0]\n                        m = LastSession.EPOCH_DATA_PARSER.findall(epoch_data)\n                        for key, value in m:\n                            if key == 'reward':\n                                reward = float(value)\n                                self.avg_reward += reward\n                                if reward < self.min_reward:\n                                    self.min_reward = reward\n\n                                elif reward > self.max_reward:\n                                    self.max_reward = reward\n\n                elif LastSession.PEER_TOKEN in line:\n                    m = self._peer_parser.findall(line)\n                    if m:\n                        name, pubkey, rssi, sid, pwnd_tot, uptime = m[0]\n                        if pubkey not in cache:\n                            self.last_peer = Peer({\n                                'session_id': sid,\n                                'channel': 1,\n                                'rssi': int(rssi),\n                                'identity': pubkey,\n                                'advertisement': {\n                                    'name': name,\n                                    'pwnd_tot': int(pwnd_tot)\n                                }})\n                            self.peers += 1\n                            cache[pubkey] = self.last_peer\n                        else:\n                            cache[pubkey].adv['pwnd_tot'] = pwnd_tot\n            except Exception as e:\n                logging.error(\"error parsing line '%s': %s\" % (line, e))\n\n        if started_at is not None:\n            self.duration = stopped_at - started_at\n            mins, secs = divmod(self.duration, 60)\n            hours, mins = divmod(mins, 60)\n        else:\n            hours = mins = secs = 0\n\n        self.duration = '%02d:%02d:%02d' % (hours, mins, secs)\n        self.duration_human = []\n        if hours > 0:\n            self.duration_human.append('%d %s' % (hours, self.voice.hhmmss(hours, 'h')))\n        if mins > 0:\n            self.duration_human.append('%d %s' % (mins, self.voice.hhmmss(mins, 'm')))\n        if secs > 0:\n            self.duration_human.append('%d %s' % (secs, self.voice.hhmmss(secs, 's')))\n\n        self.duration_human = ', '.join(self.duration_human)\n        self.avg_reward /= (self.epochs if self.epochs else 1)\n\n    def parse(self, ui, skip=False):\n        if skip:\n            logging.debug(\"skipping parsing of the last session logs ...\")\n        else:\n            logging.debug(\"reading last session logs ...\")\n\n            ui.on_reading_logs()\n\n            lines = []\n\n            if os.path.exists(self.path):\n                with FileReadBackwards(self.path, encoding=\"utf-8\") as fp:\n                    for line in fp:\n                        line = line.strip()\n                        if line != \"\" and line[0] != '[':\n                            continue\n                        lines.append(line)\n                        if LastSession.START_TOKEN in line:\n                            break\n\n                        lines_so_far = len(lines)\n                        if lines_so_far % 100 == 0:\n                            ui.on_reading_logs(lines_so_far)\n\n                lines.reverse()\n\n            if len(lines) == 0:\n                lines.append(\"Initial Session\");\n\n            ui.on_reading_logs()\n\n            self.last_session = lines\n            self.last_session_id = hashlib.md5(lines[0].encode()).hexdigest()\n            self.last_saved_session_id = self._get_last_saved_session_id()\n\n            logging.debug(\"parsing last session logs (%d lines) ...\" % len(lines))\n\n            self._parse_stats()\n        self.parsed = True\n\n    def is_new(self):\n        return self.last_session_id != self.last_saved_session_id\n\n\ndef setup_logging(args, config):\n    cfg = config['main']['log']\n    filename = cfg['path']\n\n    formatter = logging.Formatter(\"[%(asctime)s] [%(levelname)s] %(message)s\")\n    root = logging.getLogger()\n\n    root.setLevel(logging.DEBUG if args.debug else logging.INFO)\n\n    if filename:\n        # since python default log rotation might break session data in different files,\n        # we need to do log rotation ourselves\n        log_rotation(filename, cfg)\n\n        file_handler = logging.FileHandler(filename)\n        file_handler.setFormatter(formatter)\n        root.addHandler(file_handler)\n\n    console_handler = logging.StreamHandler()\n    console_handler.setFormatter(formatter)\n    root.addHandler(console_handler)\n\n    if not args.debug:\n        # disable scapy and tensorflow logging\n        logging.getLogger(\"scapy\").disabled = True\n        logging.getLogger('tensorflow').disabled = True\n        # https://stackoverflow.com/questions/15777951/how-to-suppress-pandas-future-warning\n        warnings.simplefilter(action='ignore', category=FutureWarning)\n        warnings.simplefilter(action='ignore', category=DeprecationWarning)\n        # https://stackoverflow.com/questions/24344045/how-can-i-completely-remove-any-logging-from-requests-module-in-python?noredirect=1&lq=1\n        logging.getLogger(\"urllib3\").propagate = False\n        requests_log = logging.getLogger(\"requests\")\n        requests_log.addHandler(logging.NullHandler())\n        requests_log.prpagate = False\n\n\ndef log_rotation(filename, cfg):\n    rotation = cfg['rotation']\n    if not rotation['enabled']:\n        return\n    elif not os.path.isfile(filename):\n        return\n\n    stats = os.stat(filename)\n    # specify a maximum size to rotate ( format is 10/10B, 10K, 10M 10G )\n    if rotation['size']:\n        max_size = parse_max_size(rotation['size'])\n        if stats.st_size >= max_size:\n            do_rotate(filename, stats, cfg)\n    else:\n        raise Exception(\"log rotation is enabled but log.rotation.size was not specified\")\n\n\ndef parse_max_size(s):\n    parts = re.findall(r'(^\\d+)([bBkKmMgG]?)', s)\n    if len(parts) != 1 or len(parts[0]) != 2:\n        raise Exception(\"can't parse %s as a max size\" % s)\n\n    num, unit = parts[0]\n    num = int(num)\n    unit = unit.lower()\n\n    if unit == 'k':\n        return num * 1024\n    elif unit == 'm':\n        return num * 1024 * 1024\n    elif unit == 'g':\n        return num * 1024 * 1024 * 1024\n    else:\n        return num\n\n\ndef do_rotate(filename, stats, cfg):\n    base_path = os.path.dirname(filename)\n    name = os.path.splitext(os.path.basename(filename))[0]\n    archive_filename = os.path.join(base_path, \"%s.gz\" % name)\n    counter = 2\n\n    while os.path.exists(archive_filename):\n        archive_filename = os.path.join(base_path, \"%s-%d.gz\" % (name, counter))\n        counter += 1\n\n    log_filename = archive_filename.replace('gz', 'log')\n\n    print(\"%s is %d bytes big, rotating to %s ...\" % (filename, stats.st_size, log_filename))\n\n    shutil.move(filename, log_filename)\n\n    print(\"compressing to %s ...\" % archive_filename)\n\n    with open(log_filename, 'rb') as src:\n        with gzip.open(archive_filename, 'wb') as dst:\n            dst.writelines(src)\n\n    os.remove(log_filename)\n"
  },
  {
    "path": "pwnagotchi/mesh/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/mesh/peer.py",
    "content": "import time\nimport logging\nimport datetime\n\nimport pwnagotchi.ui.faces as faces\n\n\ndef parse_rfc3339(dt):\n    if dt == \"0001-01-01T00:00:00Z\":\n        return datetime.datetime.now()\n    return datetime.datetime.strptime(dt.split('.')[0], \"%Y-%m-%dT%H:%M:%S\")\n\n\nclass Peer(object):\n    def __init__(self, obj):\n        now = time.time()\n        just_met = datetime.datetime.now().strftime(\"%Y-%m-%dT%H:%M:%S\")\n\n        try:\n            self.first_met = parse_rfc3339(obj.get('met_at', just_met))\n            self.first_seen = parse_rfc3339(obj.get('detected_at', just_met))\n            self.prev_seen = parse_rfc3339(obj.get('prev_seen_at', just_met))\n        except Exception as e:\n            logging.warning(\"error while parsing peer timestamps: %s\" % e)\n            logging.debug(e, exc_info=True)\n            self.first_met = just_met\n            self.first_seen = just_met\n            self.prev_seen = just_met\n\n        self.last_seen = now  # should be seen_at\n        self.encounters = obj.get('encounters', 0)\n        self.session_id = obj.get('session_id', '')\n        self.last_channel = obj.get('channel', 1)\n        self.rssi = obj.get('rssi', 0)\n        self.adv = obj.get('advertisement', {})\n\n    def update(self, new):\n        if self.name() != new.name():\n            logging.info(\"peer %s changed name: %s -> %s\" % (self.full_name(), self.name(), new.name()))\n\n        if self.session_id != new.session_id:\n            logging.info(\"peer %s changed session id: %s -> %s\" % (self.full_name(), self.session_id, new.session_id))\n\n        self.adv = new.adv\n        self.rssi = new.rssi\n        self.session_id = new.session_id\n        self.last_seen = time.time()\n        self.prev_seen = new.prev_seen\n        self.first_met = new.first_met\n        self.encounters = new.encounters\n\n    def inactive_for(self):\n        return time.time() - self.last_seen\n\n    def first_encounter(self):\n        return self.encounters == 1\n\n    def is_good_friend(self, config):\n        return self.encounters >= config['personality']['bond_encounters_factor']\n\n    def face(self):\n        return self.adv.get('face', faces.FRIEND)\n\n    def name(self):\n        return self.adv.get('name', '???')\n\n    def identity(self):\n        return self.adv.get('identity', '???')\n\n    def full_name(self):\n        return \"%s@%s\" % (self.name(), self.identity())\n\n    def version(self):\n        return self.adv.get('version', '1.0.0a')\n\n    def pwnd_run(self):\n        return int(self.adv.get('pwnd_run', 0))\n\n    def pwnd_total(self):\n        return int(self.adv.get('pwnd_tot', 0))\n\n    def uptime(self):\n        return self.adv.get('uptime', 0)\n\n    def epoch(self):\n        return self.adv.get('epoch', 0)\n\n    def full_name(self):\n        return '%s@%s' % (self.name(), self.identity())\n\n    def is_closer(self, other):\n        return self.rssi > other.rssi\n"
  },
  {
    "path": "pwnagotchi/mesh/utils.py",
    "content": "import _thread\nimport logging\nimport time\n\nimport pwnagotchi\nimport pwnagotchi.utils as utils\nimport pwnagotchi.ui.faces as faces\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi.grid as grid\nfrom pwnagotchi.mesh.peer import Peer\n\n\nclass AsyncAdvertiser(object):\n    def __init__(self, config, view, keypair):\n        self._config = config\n        self._view = view\n        self._keypair = keypair\n        self._advertisement = {\n            'name': pwnagotchi.name(),\n            'version': pwnagotchi.__version__,\n            'identity': self._keypair.fingerprint,\n            'face': faces.FRIEND,\n            'pwnd_run': 0,\n            'pwnd_tot': 0,\n            'uptime': 0,\n            'epoch': 0,\n            'policy': self._config['personality']\n        }\n        self._peers = {}\n        self._closest_peer = None\n\n    def fingerprint(self):\n        return self._keypair.fingerprint\n\n    def _update_advertisement(self, s):\n        self._advertisement['pwnd_run'] = len(self._handshakes)\n        self._advertisement['pwnd_tot'] = utils.total_unique_handshakes(self._config['bettercap']['handshakes'])\n        self._advertisement['uptime'] = pwnagotchi.uptime()\n        self._advertisement['epoch'] = self._epoch.epoch\n        grid.set_advertisement_data(self._advertisement)\n\n    def start_advertising(self):\n        if self._config['personality']['advertise']:\n            _thread.start_new_thread(self._adv_poller, ())\n\n            grid.set_advertisement_data(self._advertisement)\n            grid.advertise(True)\n            self._view.on_state_change('face', self._on_face_change)\n        else:\n            logging.warning(\"advertising is disabled\")\n\n    def _on_face_change(self, old, new):\n        self._advertisement['face'] = new\n        grid.set_advertisement_data(self._advertisement)\n\n    def cumulative_encounters(self):\n        return sum(peer.encounters for _, peer in self._peers.items())\n\n    def _on_new_peer(self, peer):\n        logging.info(\"new peer %s detected (%d encounters)\" % (peer.full_name(), peer.encounters))\n        self._view.on_new_peer(peer)\n        plugins.on('peer_detected', self, peer)\n\n    def _on_lost_peer(self, peer):\n        logging.info(\"lost peer %s\" % peer.full_name())\n        self._view.on_lost_peer(peer)\n        plugins.on('peer_lost', self, peer)\n\n    def _adv_poller(self):\n        # give the system a few seconds to start the first time so that any expressions\n        # due to nearby units will be rendered properly\n        time.sleep(20)\n        while True:\n            try:\n                logging.debug(\"polling pwngrid-peer for peers ...\")\n\n                grid_peers = grid.peers()\n                new_peers = {}\n\n                self._closest_peer = None\n                for obj in grid_peers:\n                    peer = Peer(obj)\n                    new_peers[peer.identity()] = peer\n                    if self._closest_peer is None:\n                        self._closest_peer = peer\n\n                # check who's gone\n                to_delete = []\n                for ident, peer in self._peers.items():\n                    if ident not in new_peers:\n                        to_delete.append(ident)\n\n                for ident in to_delete:\n                    self._on_lost_peer(self._peers[ident])\n                    del self._peers[ident]\n\n                for ident, peer in new_peers.items():\n                    # check who's new\n                    if ident not in self._peers:\n                        self._peers[ident] = peer\n                        self._on_new_peer(peer)\n                    # update the rest\n                    else:\n                        self._peers[ident].update(peer)\n\n            except Exception as e:\n                logging.warning(\"error while polling pwngrid-peer: %s\" % e)\n                logging.debug(e, exc_info=True)\n\n            time.sleep(3)\n"
  },
  {
    "path": "pwnagotchi/mesh/wifi.py",
    "content": "NumChannels = 140\nNumChannelsExt = 165  # see https://github.com/evilsocket/pwnagotchi/issues/583\n\n\ndef freq_to_channel(freq):\n    if freq <= 2472:\n        return int(((freq - 2412) / 5) + 1)\n    elif freq == 2484:\n        return int(14)\n    elif 5035 <= freq <= 5865:\n        return int(((freq - 5035) / 5) + 7)\n    else:\n        return 0\n"
  },
  {
    "path": "pwnagotchi/plugins/__init__.py",
    "content": "import os\nimport glob\nimport _thread\nimport threading\nimport importlib, importlib.util\nimport logging\n\n\n\ndefault_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), \"default\")\nloaded = {}\ndatabase = {}\nlocks = {}\n\n\nclass Plugin:\n    @classmethod\n    def __init_subclass__(cls, **kwargs):\n        super().__init_subclass__(**kwargs)\n        global loaded, locks\n\n        plugin_name = cls.__module__.split('.')[0]\n        plugin_instance = cls()\n        logging.debug(\"loaded plugin %s as %s\" % (plugin_name, plugin_instance))\n        loaded[plugin_name] = plugin_instance\n\n        for attr_name in plugin_instance.__dir__():\n            if attr_name.startswith('on_'):\n                cb = getattr(plugin_instance, attr_name, None)\n                if cb is not None and callable(cb):\n                    locks[\"%s::%s\" % (plugin_name, attr_name)] = threading.Lock()\n\n\ndef toggle_plugin(name, enable=True):\n    \"\"\"\n    Load or unload a plugin\n\n    returns True if changed, otherwise False\n    \"\"\"\n    import pwnagotchi\n    from pwnagotchi.ui import view\n    from pwnagotchi.utils import save_config\n\n    global loaded, database\n\n    if pwnagotchi.config:\n        if not name in pwnagotchi.config['main']['plugins']:\n            pwnagotchi.config['main']['plugins'][name] = dict()\n        pwnagotchi.config['main']['plugins'][name]['enabled'] = enable\n        save_config(pwnagotchi.config, '/etc/pwnagotchi/config.toml')\n\n    if not enable and name in loaded:\n        if getattr(loaded[name], 'on_unload', None):\n            loaded[name].on_unload(view.ROOT)\n        del loaded[name]\n\n        return True\n\n    if enable and name in database and name not in loaded:\n        load_from_file(database[name])\n        if name in loaded and pwnagotchi.config and name in pwnagotchi.config['main']['plugins']:\n            loaded[name].options = pwnagotchi.config['main']['plugins'][name]\n        one(name, 'loaded')\n        if pwnagotchi.config:\n            one(name, 'config_changed', pwnagotchi.config)\n        one(name, 'ui_setup', view.ROOT)\n        one(name, 'ready', view.ROOT._agent)\n        return True\n\n    return False\n\n\ndef on(event_name, *args, **kwargs):\n    for plugin_name in loaded.keys():\n        one(plugin_name, event_name, *args, **kwargs)\n\n\ndef locked_cb(lock_name, cb, *args, **kwargs):\n    global locks\n\n    if lock_name not in locks:\n        locks[lock_name] = threading.Lock()\n\n    with locks[lock_name]:\n        cb(*args, *kwargs)\n\n\ndef one(plugin_name, event_name, *args, **kwargs):\n    global loaded\n\n    if plugin_name in loaded:\n        plugin = loaded[plugin_name]\n        cb_name = 'on_%s' % event_name\n        callback = getattr(plugin, cb_name, None)\n        if callback is not None and callable(callback):\n            try:\n                lock_name = \"%s::%s\" % (plugin_name, cb_name)\n                locked_cb_args = (lock_name, callback, *args, *kwargs)\n                _thread.start_new_thread(locked_cb, locked_cb_args)\n            except Exception as e:\n                logging.error(\"error while running %s.%s : %s\" % (plugin_name, cb_name, e))\n                logging.error(e, exc_info=True)\n\n\ndef load_from_file(filename):\n    logging.debug(\"loading %s\" % filename)\n    plugin_name = os.path.basename(filename.replace(\".py\", \"\"))\n    spec = importlib.util.spec_from_file_location(plugin_name, filename)\n    instance = importlib.util.module_from_spec(spec)\n    spec.loader.exec_module(instance)\n    return plugin_name, instance\n\n\ndef load_from_path(path, enabled=()):\n    global loaded, database\n    logging.debug(\"loading plugins from %s - enabled: %s\" % (path, enabled))\n    for filename in glob.glob(os.path.join(path, \"*.py\")):\n        plugin_name = os.path.basename(filename.replace(\".py\", \"\"))\n        database[plugin_name] = filename\n        if plugin_name in enabled:\n            try:\n                load_from_file(filename)\n            except Exception as e:\n                logging.warning(\"error while loading %s: %s\" % (filename, e))\n                logging.debug(e, exc_info=True)\n\n    return loaded\n\n\ndef load(config):\n    enabled = [name for name, options in config['main']['plugins'].items() if\n               'enabled' in options and options['enabled']]\n\n    # load default plugins\n    load_from_path(default_path, enabled=enabled)\n\n    # load custom ones\n    custom_path = config['main']['custom_plugins'] if 'custom_plugins' in config['main'] else None\n    if custom_path is not None:\n        load_from_path(custom_path, enabled=enabled)\n\n    # propagate options\n    for name, plugin in loaded.items():\n        plugin.options = config['main']['plugins'][name]\n\n    on('loaded')\n    on('config_changed', config)\n"
  },
  {
    "path": "pwnagotchi/plugins/cmd.py",
    "content": "# Handles the commandline stuff\n\nimport os\nimport logging\nimport glob\nimport re\nimport shutil\nfrom fnmatch import fnmatch\nfrom pwnagotchi.utils import download_file, unzip, save_config, parse_version, md5\nfrom pwnagotchi.plugins import default_path\n\n\nSAVE_DIR = '/usr/local/share/pwnagotchi/availaible-plugins/'\nDEFAULT_INSTALL_PATH = '/usr/local/share/pwnagotchi/installed-plugins/'\n\n\ndef add_parsers(parser):\n    \"\"\"\n    Adds the plugins subcommand to a given argparse.ArgumentParser\n    \"\"\"\n    subparsers = parser.add_subparsers()\n    ## pwnagotchi plugins\n    parser_plugins = subparsers.add_parser('plugins')\n    plugin_subparsers = parser_plugins.add_subparsers(dest='plugincmd')\n\n    ## pwnagotchi plugins search\n    parser_plugins_search = plugin_subparsers.add_parser('search', help='Search for pwnagotchi plugins')\n    parser_plugins_search.add_argument('pattern', type=str, help=\"Search expression (wildcards allowed)\")\n\n    ## pwnagotchi plugins list\n    parser_plugins_list = plugin_subparsers.add_parser('list', help='List available pwnagotchi plugins')\n    parser_plugins_list.add_argument('-i', '--installed', action='store_true', required=False, help='List also installed plugins')\n\n    ## pwnagotchi plugins update\n    parser_plugins_update = plugin_subparsers.add_parser('update', help='Updates the database')\n\n    ## pwnagotchi plugins upgrade\n    parser_plugins_upgrade = plugin_subparsers.add_parser('upgrade', help='Upgrades plugins')\n    parser_plugins_upgrade.add_argument('pattern', type=str, nargs='?', default='*', help=\"Filter expression (wildcards allowed)\")\n\n    ## pwnagotchi plugins enable\n    parser_plugins_enable = plugin_subparsers.add_parser('enable', help='Enables a plugin')\n    parser_plugins_enable.add_argument('name', type=str, help='Name of the plugin')\n\n    ## pwnagotchi plugins disable\n    parser_plugins_disable = plugin_subparsers.add_parser('disable', help='Disables a plugin')\n    parser_plugins_disable.add_argument('name', type=str, help='Name of the plugin')\n\n    ## pwnagotchi plugins install\n    parser_plugins_install = plugin_subparsers.add_parser('install', help='Installs a plugin')\n    parser_plugins_install.add_argument('name', type=str, help='Name of the plugin')\n\n    ## pwnagotchi plugins uninstall\n    parser_plugins_uninstall = plugin_subparsers.add_parser('uninstall', help='Uninstalls a plugin')\n    parser_plugins_uninstall.add_argument('name', type=str, help='Name of the plugin')\n\n    ## pwnagotchi plugins edit\n    parser_plugins_edit = plugin_subparsers.add_parser('edit', help='Edit the options')\n    parser_plugins_edit.add_argument('name', type=str, help='Name of the plugin')\n\n    return parser\n\n\ndef used_plugin_cmd(args):\n    \"\"\"\n    Checks if the plugins subcommand was used\n    \"\"\"\n    return hasattr(args, 'plugincmd')\n\n\ndef handle_cmd(args, config):\n    \"\"\"\n    Parses the arguments and does the thing the user wants\n    \"\"\"\n    if args.plugincmd == 'update':\n        return update(config)\n    elif args.plugincmd == 'search':\n        args.installed = True # also search in installed plugins\n        return list_plugins(args, config, args.pattern)\n    elif args.plugincmd == 'install':\n        return install(args, config)\n    elif args.plugincmd == 'uninstall':\n        return uninstall(args, config)\n    elif args.plugincmd == 'list':\n        return list_plugins(args, config)\n    elif args.plugincmd == 'enable':\n        return enable(args, config)\n    elif args.plugincmd == 'disable':\n        return disable(args, config)\n    elif args.plugincmd == 'upgrade':\n        return upgrade(args, config, args.pattern)\n    elif args.plugincmd == 'edit':\n        return edit(args, config)\n\n    raise NotImplementedError()\n\n\ndef edit(args, config):\n    \"\"\"\n    Edit the config of the plugin\n    \"\"\"\n    plugin = args.name\n    editor = os.environ.get('EDITOR', 'vim') # because vim is the best\n\n    if plugin not in config['main']['plugins']:\n        return 1\n\n    plugin_config = {'main': {'plugins': {plugin: config['main']['plugins'][plugin]}}}\n\n    import toml\n    from subprocess import call\n    from tempfile import NamedTemporaryFile\n    from pwnagotchi.utils import DottedTomlEncoder\n\n    new_plugin_config = None\n    with NamedTemporaryFile(suffix=\".tmp\", mode='r+t') as tmp:\n        tmp.write(toml.dumps(plugin_config, encoder=DottedTomlEncoder()))\n        tmp.flush()\n        rc = call([editor, tmp.name])\n        if rc != 0:\n            return rc\n        tmp.seek(0)\n        new_plugin_config = toml.load(tmp)\n\n    config['main']['plugins'][plugin] = new_plugin_config['main']['plugins'][plugin]\n    save_config(config, args.user_config)\n    return 0\n\n\ndef enable(args, config):\n    \"\"\"\n    Enables the given plugin and saves the config to disk\n    \"\"\"\n    if args.name not in config['main']['plugins']:\n        config['main']['plugins'][args.name] = dict()\n    config['main']['plugins'][args.name]['enabled'] = True\n    save_config(config, args.user_config)\n    return 0\n\n\ndef disable(args, config):\n    \"\"\"\n    Disables the given plugin and saves the config to disk\n    \"\"\"\n    if args.name not in config['main']['plugins']:\n        config['main']['plugins'][args.name] = dict()\n    config['main']['plugins'][args.name]['enabled'] = False\n    save_config(config, args.user_config)\n    return 0\n\n\ndef upgrade(args, config, pattern='*'):\n    \"\"\"\n    Upgrades the given plugin\n    \"\"\"\n    available = _get_available()\n    installed = _get_installed(config)\n\n    for plugin, filename in installed.items():\n        if not fnmatch(plugin, pattern) or plugin not in available:\n            continue\n\n        available_version = _extract_version(available[plugin])\n        installed_version = _extract_version(filename)\n\n        if installed_version and available_version:\n                if available_version <= installed_version:\n                    continue\n        else:\n            continue\n\n        logging.info('Upgrade %s from %s to %s', plugin, '.'.join(installed_version), '.'.join(available_version))\n        shutil.copyfile(available[plugin], installed[plugin])\n\n        # maybe has config\n        for conf in glob.glob(available[plugin].replace('.py', '.y?ml')):\n            dst = os.path.join(os.path.dirname(installed[plugin]), os.path.basename(conf))\n            if os.path.exists(dst) and md5(dst) != md5(conf):\n                # backup\n                logging.info('Backing up config: %s', os.path.basename(conf))\n                shutil.move(dst, dst + '.bak')\n            shutil.copyfile(conf, dst)\n\n    return 0\n\n\ndef list_plugins(args, config, pattern='*'):\n    \"\"\"\n    Lists the available and installed plugins\n    \"\"\"\n    found = False\n\n    line = \"|{name:^{width}}|{version:^9}|{enabled:^10}|{status:^15}|\"\n\n    available = _get_available()\n    installed = _get_installed(config)\n\n    available_and_installed = set(list(available.keys()) + list(installed.keys()))\n    available_not_installed = set(available.keys()) - set(installed.keys())\n\n    max_len_list = available_and_installed if args.installed else available_not_installed\n    max_len = max(map(len, max_len_list))\n    header = line.format(name='Plugin', width=max_len, version='Version', enabled='Active', status='Status')\n    line_length = max(max_len, len('Plugin')) + len(header) - len('Plugin') - 12 # lol\n\n    print('-' * line_length)\n    print(header)\n    print('-' * line_length)\n\n    if args.installed:\n        # only installed (maybe update available?)\n        for plugin, filename in sorted(installed.items()):\n            if not fnmatch(plugin, pattern):\n                continue\n            found = True\n            installed_version = _extract_version(filename)\n            available_version = None\n            if plugin in available:\n                available_version = _extract_version(available[plugin])\n\n            status = \"installed\"\n            if installed_version and available_version:\n                if available_version > installed_version:\n                    status = \"installed (^)\"\n\n            enabled = 'enabled' if plugin in config['main']['plugins'] and \\\n                'enabled' in config['main']['plugins'][plugin] and \\\n                    config['main']['plugins'][plugin]['enabled'] \\\n                        else 'disabled'\n\n            print(line.format(name=plugin, width=max_len, version='.'.join(installed_version), enabled=enabled, status=status))\n\n\n    for plugin in sorted(available_not_installed):\n        if not fnmatch(plugin, pattern):\n            continue\n        found = True\n        available_version = _extract_version(available[plugin])\n        print(line.format(name=plugin, width=max_len, version='.'.join(available_version), enabled='-', status='available'))\n\n    print('-' * line_length)\n\n    if not found:\n        logging.info('Maybe try: pwnagotchi plugins update')\n        return 1\n    return 0\n\n\ndef _extract_version(filename):\n    \"\"\"\n    Extracts the version from a python file\n    \"\"\"\n    plugin_content = open(filename, 'rt').read()\n    m = re.search(r'__version__[\\t ]*=[\\t ]*[\\'\\\"]([^\\\"\\']+)', plugin_content)\n    if m:\n        return parse_version(m.groups()[0])\n    return None\n\n\ndef _get_available():\n    \"\"\"\n    Get all availaible plugins\n    \"\"\"\n    available = dict()\n    for filename in glob.glob(os.path.join(SAVE_DIR, \"*.py\")):\n        plugin_name = os.path.basename(filename.replace(\".py\", \"\"))\n        available[plugin_name] = filename\n    return available\n\n\ndef _get_installed(config):\n    \"\"\"\n    Get all installed plugins\n    \"\"\"\n    installed = dict()\n    search_dirs = [ default_path, config['main']['custom_plugins'] ]\n    for search_dir in search_dirs:\n        if search_dir:\n            for filename in glob.glob(os.path.join(search_dir, \"*.py\")):\n                plugin_name = os.path.basename(filename.replace(\".py\", \"\"))\n                installed[plugin_name] = filename\n    return installed\n\n\ndef uninstall(args, config):\n    \"\"\"\n    Uninstalls a plugin\n    \"\"\"\n    plugin_name = args.name\n    installed = _get_installed(config)\n    if plugin_name not in installed:\n        logging.error('Plugin %s is not installed.', plugin_name)\n        return 1\n    os.remove(installed[plugin_name])\n    return 0\n\n\ndef install(args, config):\n    \"\"\"\n    Installs the given plugin\n    \"\"\"\n    global DEFAULT_INSTALL_PATH\n    plugin_name = args.name\n    available = _get_available()\n    installed = _get_installed(config)\n\n    if plugin_name not in available:\n        logging.error('%s not found.', plugin_name)\n        return 1\n\n    if plugin_name in installed:\n        logging.error('%s already installed.', plugin_name)\n\n    # install into custom_plugins path\n    install_path = config['main']['custom_plugins']\n    if not install_path:\n        install_path = DEFAULT_INSTALL_PATH\n        config['main']['custom_plugins'] = install_path\n        save_config(config, args.user_config)\n\n    os.makedirs(install_path, exist_ok=True)\n\n    shutil.copyfile(available[plugin_name], os.path.join(install_path, os.path.basename(available[plugin_name])))\n\n    # maybe has config\n    for conf in glob.glob(available[plugin_name].replace('.py', '.y?ml')):\n        dst = os.path.join(install_path, os.path.basename(conf))\n        if os.path.exists(dst) and md5(dst) != md5(conf):\n            # backup\n            logging.info('Backing up config: %s', os.path.basename(conf))\n            shutil.move(dst, dst + '.bak')\n        shutil.copyfile(conf, dst)\n\n    return 0\n\n\ndef _analyse_dir(path):\n    results = dict()\n    path += '*' if path.endswith('/') else '/*'\n    for filename in glob.glob(path, recursive=True):\n        if not os.path.isfile(filename):\n            continue\n        try:\n            results[filename] = md5(filename)\n        except OSError:\n            continue\n    return results\n\n\ndef update(config):\n    \"\"\"\n    Updates the database\n    \"\"\"\n    global SAVE_DIR\n\n    urls = config['main']['custom_plugin_repos']\n    if not urls:\n        logging.info('No plugin repositories configured.')\n        return 1\n\n    rc = 0\n    for idx, REPO_URL in enumerate(urls):\n        DEST = os.path.join(SAVE_DIR, 'plugins%d.zip' % idx)\n        logging.info('Downloading plugins from %s to %s', REPO_URL, DEST)\n\n        try:\n            os.makedirs(SAVE_DIR, exist_ok=True)\n            before_update = _analyse_dir(SAVE_DIR)\n\n            download_file(REPO_URL, os.path.join(SAVE_DIR, DEST))\n\n            logging.info('Unzipping...')\n            unzip(DEST, SAVE_DIR, strip_dirs=1)\n\n            after_update = _analyse_dir(SAVE_DIR)\n\n            b_len = len(before_update)\n            a_len = len(after_update)\n\n            if a_len > b_len:\n                logging.info('Found %d new file(s).', a_len - b_len)\n\n            changed = 0\n            for filename, filehash in after_update.items():\n                if filename in before_update and filehash != before_update[filename]:\n                    changed += 1\n\n            if changed:\n                logging.info('%d file(s) were changed.', changed)\n\n        except Exception as ex:\n            logging.error('Error while updating plugins: %s', ex)\n            rc = 1\n    return rc\n"
  },
  {
    "path": "pwnagotchi/plugins/default/auto-update.py",
    "content": "import os\nimport re\nimport logging\nimport subprocess\nimport requests\nimport platform\nimport shutil\nimport glob\nfrom threading import Lock\n\nimport pwnagotchi\nimport pwnagotchi.plugins as plugins\nfrom pwnagotchi.utils import StatusFile, parse_version as version_to_tuple\n\n\ndef check(version, repo, native=True):\n    logging.debug(\"checking remote version for %s, local is %s\" % (repo, version))\n    info = {\n        'repo': repo,\n        'current': version,\n        'available': None,\n        'url': None,\n        'native': native,\n        'arch': platform.machine()\n    }\n\n    resp = requests.get(\"https://api.github.com/repos/%s/releases/latest\" % repo)\n    latest = resp.json()\n    info['available'] = latest_ver = latest['tag_name'].replace('v', '')\n    is_arm = info['arch'].startswith('arm')\n\n    local = version_to_tuple(info['current'])\n    remote = version_to_tuple(latest_ver)\n    if remote > local:\n        if not native:\n            info['url'] = \"https://github.com/%s/archive/%s.zip\" % (repo, latest['tag_name'])\n        else:\n            # check if this release is compatible with arm6\n            for asset in latest['assets']:\n                download_url = asset['browser_download_url']\n                if download_url.endswith('.zip') and (\n                        info['arch'] in download_url or (is_arm and 'armhf' in download_url)):\n                    info['url'] = download_url\n                    break\n\n    return info\n\n\ndef make_path_for(name):\n    path = os.path.join(\"/tmp/updates/\", name)\n    if os.path.exists(path):\n        logging.debug(\"[update] deleting %s\" % path)\n        shutil.rmtree(path, ignore_errors=True, onerror=None)\n    os.makedirs(path)\n    return path\n\n\ndef download_and_unzip(name, path, display, update):\n    target = \"%s_%s.zip\" % (name, update['available'])\n    target_path = os.path.join(path, target)\n\n    logging.info(\"[update] downloading %s to %s ...\" % (update['url'], target_path))\n    display.update(force=True, new_data={'status': 'Downloading %s %s ...' % (name, update['available'])})\n\n    os.system('wget -q \"%s\" -O \"%s\"' % (update['url'], target_path))\n\n    logging.info(\"[update] extracting %s to %s ...\" % (target_path, path))\n    display.update(force=True, new_data={'status': 'Extracting %s %s ...' % (name, update['available'])})\n\n    os.system('unzip \"%s\" -d \"%s\"' % (target_path, path))\n\n\ndef verify(name, path, source_path, display, update):\n    display.update(force=True, new_data={'status': 'Verifying %s %s ...' % (name, update['available'])})\n\n    checksums = glob.glob(\"%s/*.sha256\" % path)\n    if len(checksums) == 0:\n        if update['native']:\n            logging.warning(\"[update] native update without SHA256 checksum file\")\n            return False\n\n    else:\n        checksum = checksums[0]\n\n        logging.info(\"[update] verifying %s for %s ...\" % (checksum, source_path))\n\n        with open(checksum, 'rt') as fp:\n            expected = fp.read().split('=')[1].strip().lower()\n\n        real = subprocess.getoutput('sha256sum \"%s\"' % source_path).split(' ')[0].strip().lower()\n\n        if real != expected:\n            logging.warning(\"[update] checksum mismatch for %s: expected=%s got=%s\" % (source_path, expected, real))\n            return False\n\n    return True\n\n\ndef install(display, update):\n    name = update['repo'].split('/')[1]\n\n    path = make_path_for(name)\n\n    download_and_unzip(name, path, display, update)\n\n    source_path = os.path.join(path, name)\n    if not verify(name, path, source_path, display, update):\n        return False\n\n    logging.info(\"[update] installing %s ...\" % name)\n    display.update(force=True, new_data={'status': 'Installing %s %s ...' % (name, update['available'])})\n\n    if update['native']:\n        dest_path = subprocess.getoutput(\"which %s\" % name)\n        if dest_path == \"\":\n            logging.warning(\"[update] can't find path for %s\" % name)\n            return False\n\n        logging.info(\"[update] stopping %s ...\" % update['service'])\n        os.system(\"service %s stop\" % update['service'])\n        os.system(\"mv %s %s\" % (source_path, dest_path))\n        logging.info(\"[update] restarting %s ...\" % update['service'])\n        os.system(\"service %s start\" % update['service'])\n    else:\n        if not os.path.exists(source_path):\n            source_path = \"%s-%s\" % (source_path, update['available'])\n\n        # setup.py is going to install data files for us\n        os.system(\"cd %s && pip3 install .\" % source_path)\n\n    return True\n\n\ndef parse_version(cmd):\n    out = subprocess.getoutput(cmd)\n    for part in out.split(' '):\n        part = part.replace('v', '').strip()\n        if re.search(r'^\\d+\\.\\d+\\.\\d+.*$', part):\n            return part\n    raise Exception('could not parse version from \"%s\": output=\\n%s' % (cmd, out))\n\n\nclass AutoUpdate(plugins.Plugin):\n    __author__ = 'evilsocket@gmail.com'\n    __version__ = '1.1.1'\n    __name__ = 'auto-update'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin checks when updates are available and applies them when internet is available.'\n\n    def __init__(self):\n        self.ready = False\n        self.status = StatusFile('/root/.auto-update')\n        self.lock = Lock()\n\n    def on_loaded(self):\n        if 'interval' not in self.options or ('interval' in self.options and not self.options['interval']):\n            logging.error(\"[update] main.plugins.auto-update.interval is not set\")\n            return\n        self.ready = True\n        logging.info(\"[update] plugin loaded.\")\n\n    def on_internet_available(self, agent):\n        if self.lock.locked():\n            return\n\n        with self.lock:\n            logging.debug(\"[update] internet connectivity is available (ready %s)\" % self.ready)\n\n            if not self.ready:\n                return\n\n            if self.status.newer_then_hours(self.options['interval']):\n                logging.debug(\"[update] last check happened less than %d hours ago\" % self.options['interval'])\n                return\n\n            logging.info(\"[update] checking for updates ...\")\n\n            display = agent.view()\n            prev_status = display.get('status')\n\n            try:\n                display.update(force=True, new_data={'status': 'Checking for updates ...'})\n\n                to_install = []\n                to_check = [\n                    ('bettercap/bettercap', parse_version('bettercap -version'), True, 'bettercap'),\n                    ('evilsocket/pwngrid', parse_version('pwngrid -version'), True, 'pwngrid-peer'),\n                    ('evilsocket/pwnagotchi', pwnagotchi.__version__, False, 'pwnagotchi')\n                ]\n\n                for repo, local_version, is_native, svc_name in to_check:\n                    info = check(local_version, repo, is_native)\n                    if info['url'] is not None:\n                        logging.warning(\n                            \"update for %s available (local version is '%s'): %s\" % (\n                                repo, info['current'], info['url']))\n                        info['service'] = svc_name\n                        to_install.append(info)\n\n                num_updates = len(to_install)\n                num_installed = 0\n\n                if num_updates > 0:\n                    if self.options['install']:\n                        for update in to_install:\n                            plugins.on('updating')\n                            if install(display, update):\n                                num_installed += 1\n                    else:\n                        prev_status = '%d new update%c available!' % (num_updates, 's' if num_updates > 1 else '')\n\n                logging.info(\"[update] done\")\n\n                self.status.update()\n\n                if num_installed > 0:\n                    display.update(force=True, new_data={'status': 'Rebooting ...'})\n                    pwnagotchi.reboot()\n\n            except Exception as e:\n                logging.error(\"[update] %s\" % e)\n\n            display.update(force=True, new_data={'status': prev_status if prev_status is not None else ''})\n"
  },
  {
    "path": "pwnagotchi/plugins/default/bt-tether.py",
    "content": "import logging\nimport os\nimport subprocess\nimport time\nfrom threading import Lock\n\nimport dbus\n\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.components import LabeledValue\nfrom pwnagotchi.ui.view import BLACK\nfrom pwnagotchi.utils import StatusFile\n\n\nclass BTError(Exception):\n    \"\"\"\n    Custom bluetooth exception\n    \"\"\"\n    pass\n\n\nclass BTNap:\n    \"\"\"\n    This class creates a bluetooth connection to the specified bt-mac\n\n    see https://github.com/bablokb/pi-btnap/blob/master/files/usr/local/sbin/btnap.service.py\n    \"\"\"\n\n    IFACE_BASE = 'org.bluez'\n    IFACE_DEV = 'org.bluez.Device1'\n    IFACE_ADAPTER = 'org.bluez.Adapter1'\n    IFACE_PROPS = 'org.freedesktop.DBus.Properties'\n\n    def __init__(self, mac):\n        self._mac = mac\n\n    @staticmethod\n    def get_bus():\n        \"\"\"\n        Get systembus obj\n        \"\"\"\n        bus = getattr(BTNap.get_bus, 'cached_obj', None)\n        if not bus:\n            bus = BTNap.get_bus.cached_obj = dbus.SystemBus()\n        return bus\n\n    @staticmethod\n    def get_manager():\n        \"\"\"\n        Get manager obj\n        \"\"\"\n        manager = getattr(BTNap.get_manager, 'cached_obj', None)\n        if not manager:\n            manager = BTNap.get_manager.cached_obj = dbus.Interface(\n                BTNap.get_bus().get_object(BTNap.IFACE_BASE, '/'),\n                'org.freedesktop.DBus.ObjectManager')\n        return manager\n\n    @staticmethod\n    def prop_get(obj, k, iface=None):\n        \"\"\"\n        Get a property of the obj\n        \"\"\"\n        if iface is None:\n            iface = obj.dbus_interface\n        return obj.Get(iface, k, dbus_interface=BTNap.IFACE_PROPS)\n\n    @staticmethod\n    def prop_set(obj, k, v, iface=None):\n        \"\"\"\n        Set a property of the obj\n        \"\"\"\n        if iface is None:\n            iface = obj.dbus_interface\n        return obj.Set(iface, k, v, dbus_interface=BTNap.IFACE_PROPS)\n\n    @staticmethod\n    def find_adapter(pattern=None):\n        \"\"\"\n        Find the bt adapter\n        \"\"\"\n\n        return BTNap.find_adapter_in_objects(BTNap.get_manager().GetManagedObjects(), pattern)\n\n    @staticmethod\n    def find_adapter_in_objects(objects, pattern=None):\n        \"\"\"\n        Finds the obj with a pattern\n        \"\"\"\n        bus, obj = BTNap.get_bus(), None\n        for path, ifaces in objects.items():\n            adapter = ifaces.get(BTNap.IFACE_ADAPTER)\n            if adapter is None:\n                continue\n            if not pattern or pattern == adapter['Address'] or path.endswith(pattern):\n                obj = bus.get_object(BTNap.IFACE_BASE, path)\n                yield dbus.Interface(obj, BTNap.IFACE_ADAPTER)\n        if obj is None:\n            raise BTError('Bluetooth adapter not found')\n\n    @staticmethod\n    def find_device(device_address, adapter_pattern=None):\n        \"\"\"\n        Finds the device\n        \"\"\"\n        return BTNap.find_device_in_objects(BTNap.get_manager().GetManagedObjects(),\n                                            device_address, adapter_pattern)\n\n    @staticmethod\n    def find_device_in_objects(objects, device_address, adapter_pattern=None):\n        \"\"\"\n        Finds the device in objects\n        \"\"\"\n        bus = BTNap.get_bus()\n        path_prefix = ''\n        if adapter_pattern:\n            if not isinstance(adapter_pattern, str):\n                adapter = adapter_pattern\n            else:\n                adapter = BTNap.find_adapter_in_objects(objects, adapter_pattern)\n            path_prefix = adapter.object_path\n        for path, ifaces in objects.items():\n            device = ifaces.get(BTNap.IFACE_DEV)\n            if device is None:\n                continue\n            if str(device['Address']).lower() == device_address.lower() and path.startswith(path_prefix):\n                obj = bus.get_object(BTNap.IFACE_BASE, path)\n                return dbus.Interface(obj, BTNap.IFACE_DEV)\n        raise BTError('Bluetooth device not found')\n\n    def power(self, on=True):\n        \"\"\"\n        Set power of devices to on/off\n        \"\"\"\n        logging.debug(\"BT-TETHER: Changing bluetooth device to %s\", str(on))\n\n        try:\n            devs = list(BTNap.find_adapter())\n            devs = dict((BTNap.prop_get(dev, 'Address'), dev) for dev in devs)\n        except BTError as bt_err:\n            logging.error(bt_err)\n            return None\n\n        for dev_addr, dev in devs.items():\n            BTNap.prop_set(dev, 'Powered', on)\n            logging.debug('Set power of %s (addr %s) to %s', dev.object_path, dev_addr, str(on))\n\n        if devs:\n            return list(devs.values())[0]\n\n        return None\n\n\n    def is_paired(self):\n        \"\"\"\n        Check if already connected\n        \"\"\"\n        logging.debug(\"BT-TETHER: Checking if device is paired\")\n\n        bt_dev = self.power(True)\n\n        if not bt_dev:\n            logging.debug(\"BT-TETHER: No bluetooth device found.\")\n            return False\n\n        try:\n            dev_remote = BTNap.find_device(self._mac, bt_dev)\n            return bool(BTNap.prop_get(dev_remote, 'Paired'))\n        except BTError:\n            logging.debug(\"BT-TETHER: Device is not paired.\")\n        return False\n\n    def wait_for_device(self, timeout=15):\n        \"\"\"\n        Wait for device\n\n        returns device if found None if not\n        \"\"\"\n        logging.debug(\"BT-TETHER: Waiting for device\")\n\n        bt_dev = self.power(True)\n\n        if not bt_dev:\n            logging.debug(\"BT-TETHER: No bluetooth device found.\")\n            return None\n\n        try:\n            logging.debug(\"BT-TETHER: Starting discovery ...\")\n            bt_dev.StartDiscovery()\n        except Exception as bt_ex:\n            logging.error(bt_ex)\n            raise bt_ex\n\n        dev_remote = None\n\n        # could be set to 0, so check if > -1\n        while timeout > -1:\n            try:\n                dev_remote = BTNap.find_device(self._mac, bt_dev)\n                logging.debug(\"BT-TETHER: Using remote device (addr: %s): %s\",\n                              BTNap.prop_get(dev_remote, 'Address'), dev_remote.object_path)\n                break\n            except BTError:\n                logging.debug(\"BT-TETHER: Not found yet ...\")\n\n            time.sleep(1)\n            timeout -= 1\n\n        try:\n            logging.debug(\"BT-TETHER: Stopping Discovery ...\")\n            bt_dev.StopDiscovery()\n        except Exception as bt_ex:\n            logging.error(bt_ex)\n            raise bt_ex\n\n        return dev_remote\n\n    @staticmethod\n    def pair(device):\n        logging.debug('BT-TETHER: Trying to pair ...')\n        try:\n            device.Pair()\n            logging.debug('BT-TETHER: Successful paired with device ;)')\n            return True\n        except dbus.exceptions.DBusException as err:\n            if err.get_dbus_name() == 'org.bluez.Error.AlreadyExists':\n                logging.debug('BT-TETHER: Already paired ...')\n                return True\n        except Exception:\n            pass\n        return False\n\n    @staticmethod\n    def nap(device):\n        logging.debug('BT-TETHER: Trying to nap ...')\n\n        try:\n            logging.debug('BT-TETHER: Connecting to profile ...')\n            device.ConnectProfile('nap')\n        except Exception:  # raises exception, but still works\n            pass\n\n        net = dbus.Interface(device, 'org.bluez.Network1')\n\n        try:\n            logging.debug('BT-TETHER: Connecting to nap network ...')\n            net.Connect('nap')\n            return net, True\n        except dbus.exceptions.DBusException as err:\n            if err.get_dbus_name() == 'org.bluez.Error.AlreadyConnected':\n                return net, True\n\n            connected = BTNap.prop_get(net, 'Connected')\n            if not connected:\n                return None, False\n            return net, True\n\n\nclass SystemdUnitWrapper:\n    \"\"\"\n    systemd wrapper\n    \"\"\"\n\n    def __init__(self, unit):\n        self.unit = unit\n\n    @staticmethod\n    def _action_on_unit(action, unit):\n        process = subprocess.Popen(f\"systemctl {action} {unit}\", shell=True, stdin=None,\n                                   stdout=open(\"/dev/null\", \"w\"), stderr=None, executable=\"/bin/bash\")\n        process.wait()\n        if process.returncode > 0:\n            return False\n        return True\n\n    @staticmethod\n    def daemon_reload():\n        \"\"\"\n        Calls systemctl daemon-reload\n        \"\"\"\n        process = subprocess.Popen(\"systemctl daemon-reload\", shell=True, stdin=None,\n                                   stdout=open(\"/dev/null\", \"w\"), stderr=None, executable=\"/bin/bash\")\n        process.wait()\n        if process.returncode > 0:\n            return False\n        return True\n\n    def is_active(self):\n        \"\"\"\n        Checks if unit is active\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('is-active', self.unit)\n\n    def is_enabled(self):\n        \"\"\"\n        Checks if unit is enabled\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('is-enabled', self.unit)\n\n    def is_failed(self):\n        \"\"\"\n        Checks if unit is failed\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('is-failed', self.unit)\n\n    def enable(self):\n        \"\"\"\n        Enables the unit\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('enable', self.unit)\n\n    def disable(self):\n        \"\"\"\n        Disables the unit\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('disable', self.unit)\n\n    def start(self):\n        \"\"\"\n        Starts the unit\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('start', self.unit)\n\n    def stop(self):\n        \"\"\"\n        Stops the unit\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('stop', self.unit)\n\n    def restart(self):\n        \"\"\"\n        Restarts the unit\n        \"\"\"\n        return SystemdUnitWrapper._action_on_unit('restart', self.unit)\n\n\nclass IfaceWrapper:\n    \"\"\"\n    Small wrapper to check and manage ifaces\n\n    see: https://github.com/rlisagor/pynetlinux/blob/master/pynetlinux/ifconfig.py\n    \"\"\"\n\n    def __init__(self, iface):\n        self.iface = iface\n        self.path = f\"/sys/class/net/{iface}\"\n\n    def exists(self):\n        \"\"\"\n        Checks if iface exists\n        \"\"\"\n        return os.path.exists(self.path)\n\n    def is_up(self):\n        \"\"\"\n        Checks if iface is ip\n        \"\"\"\n        return open(f\"{self.path}/operstate\", 'r').read().rsplit('\\n') == 'up'\n\n    def set_addr(self, addr):\n        \"\"\"\n        Set the netmask\n        \"\"\"\n        process = subprocess.Popen(f\"ip addr add {addr} dev {self.iface}\", shell=True, stdin=None,\n                                   stdout=open(\"/dev/null\", \"w\"), stderr=None, executable=\"/bin/bash\")\n        process.wait()\n\n        if process.returncode == 2 or process.returncode == 0:  # 2 = already set\n            return True\n\n        return False\n\n    @staticmethod\n    def set_route(gateway, device):\n        process = subprocess.Popen(f\"ip route replace default via {gateway} dev {device}\", shell=True, stdin=None,\n                                   stdout=open(\"/dev/null\", \"w\"), stderr=None, executable=\"/bin/bash\")\n        process.wait()\n\n        if process.returncode > 0:\n            return False\n\n        return True\n\n\nclass Device:\n    def __init__(self, name, share_internet, mac, ip, netmask, interval, gateway=None, priority=10, scantime=15, search_order=0, max_tries=0, **kwargs):\n        self.name = name\n        self.status = StatusFile(f'/root/.bt-tether-{name}')\n        self.status.update()\n        self.tries = 0\n        self.network = None\n\n        self.max_tries = max_tries\n        self.search_order = search_order\n        self.share_internet = share_internet\n        self.ip = ip\n        self.netmask = netmask\n        self.gateway = gateway\n        self.interval = interval\n        self.mac = mac\n        self.scantime = scantime\n        self.priority = priority\n\n    def connected(self):\n        \"\"\"\n        Checks if device is connected\n        \"\"\"\n        return self.network and BTNap.prop_get(self.network, 'Connected')\n\n    def interface(self):\n        \"\"\"\n        Returns the interface name or None\n        \"\"\"\n        if not self.connected():\n            return None\n        return BTNap.prop_get(self.network, 'Interface')\n\n\nclass BTTether(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '1.1.0'\n    __license__ = 'GPL3'\n    __description__ = 'This makes the display reachable over bluetooth'\n\n\n    def __init__(self):\n        self.ready = False\n        self.options = dict()\n        self.devices = dict()\n        self.lock = Lock()\n        self.running = True\n        self.status = '-'\n\n\n    def on_loaded(self):\n        # new config\n        if 'devices' in self.options:\n            for device, options in self.options['devices'].items():\n                if 'enabled' in options and options['enabled']:\n                    for device_opt in ['enabled', 'priority', 'scantime', 'search_order',\n                                       'max_tries', 'share_internet', 'mac', 'ip',\n                                       'netmask', 'interval']:\n                        if device_opt not in options or options[device_opt] is None:\n                            logging.error(\"BT-TETHER: Please specify the %s for device %s.\",\n                                          device_opt, device)\n                            break\n                    else:\n                        if options['enabled']:\n                            self.devices[device] = Device(name=device, **options)\n\n        # legacy\n        if 'mac' in self.options:\n            for opt in ['share_internet', 'mac', 'ip', 'netmask', 'interval']:\n                if opt not in self.options or self.options[opt] is None:\n                    logging.error(\"BT-TETHER: Please specify the %s in your config.toml.\", opt)\n                    return\n\n            self.devices['legacy'] = Device(name='legacy', **self.options)\n\n        if not self.devices:\n            logging.error(\"BT-TETHER: No valid devices found\")\n            return\n\n        # ensure bluetooth is running\n        bt_unit = SystemdUnitWrapper('bluetooth.service')\n        if not bt_unit.is_active():\n            if not bt_unit.start():\n                logging.error(\"BT-TETHER: Can't start bluetooth.service\")\n                return\n\n        logging.info(\"BT-TETHER: Successfully loaded ...\")\n\n        while self.running:\n            time.sleep(1)\n\n            devices_to_try = list()\n            connected_priorities = list()\n            any_device_connected = False # if this is true, last status on screen should be C\n\n            for _, device in self.devices.items():\n                if device.connected():\n                    connected_priorities.append(device.priority)\n                    any_device_connected = True\n                    continue\n\n                if not device.max_tries or (device.max_tries > device.tries):\n                    if not device.status.newer_then_minutes(device.interval):\n                        devices_to_try.append(device)\n                        device.status.update()\n                        device.tries += 1\n\n            sorted_devices = sorted(devices_to_try, key=lambda x: x.search_order)\n\n            for device in sorted_devices:\n                bt = BTNap(device.mac)\n\n                try:\n                    logging.debug('BT-TETHER: Search %d secs for %s ...', device.scantime, device.name)\n                    dev_remote = bt.wait_for_device(timeout=device.scantime)\n                    if dev_remote is None:\n                        logging.debug('BT-TETHER: Could not find %s, try again in %d minutes.', device.name, device.interval)\n                        self.status = 'NF'\n                        continue\n                except Exception as bt_ex:\n                    logging.error(bt_ex)\n                    self.status = 'NF'\n                    continue\n\n                paired = bt.is_paired()\n                if not paired:\n                    if BTNap.pair(dev_remote):\n                        logging.debug('BT-TETHER: Paired with %s.', device.name)\n                    else:\n                        logging.debug('BT-TETHER: Pairing with %s failed ...', device.name)\n                        self.status = 'PE'\n                        continue\n                else:\n                    logging.debug('BT-TETHER: Already paired.')\n\n\n                logging.debug('BT-TETHER: Try to create nap connection with %s ...', device.name)\n                device.network, success = BTNap.nap(dev_remote)\n                interface = None\n\n                if success:\n                    try:\n                        interface = device.interface()\n                    except Exception:\n                        logging.debug('BT-TETHER: Could not establish nap connection with %s', device.name)\n                        continue\n\n                    if interface is None:\n                        self.status = 'BE'\n                        logging.debug('BT-TETHER: Could not establish nap connection with %s', device.name)\n                        continue\n\n                    logging.debug('BT-TETHER: Created interface (%s)', interface)\n                    self.status = 'C'\n                    any_device_connected = True\n                    device.tries = 0 # reset tries\n                else:\n                    logging.debug('BT-TETHER: Could not establish nap connection with %s', device.name)\n                    self.status = 'NF'\n                    continue\n\n                addr = f\"{device.ip}/{device.netmask}\"\n                if device.gateway:\n                    gateway = device.gateway\n                else:\n                    gateway = \".\".join(device.ip.split('.')[:-1] + ['1'])\n\n                wrapped_interface = IfaceWrapper(interface)\n                logging.debug('BT-TETHER: Add ip to %s', interface)\n                if not wrapped_interface.set_addr(addr):\n                    self.status = 'AE'\n                    logging.debug(\"BT-TETHER: Could not add ip to %s\", interface)\n                    continue\n\n                if device.share_internet:\n                    if not connected_priorities or device.priority > max(connected_priorities):\n                        logging.debug('BT-TETHER: Set default route to %s via %s', gateway, interface)\n                        IfaceWrapper.set_route(gateway, interface)\n                        connected_priorities.append(device.priority)\n\n                        logging.debug('BT-TETHER: Change resolv.conf if necessary ...')\n                        with open('/etc/resolv.conf', 'r+') as resolv:\n                            nameserver = resolv.read()\n                            if 'nameserver 9.9.9.9' not in nameserver:\n                                logging.debug('BT-TETHER: Added nameserver')\n                                resolv.seek(0)\n                                resolv.write(nameserver + 'nameserver 9.9.9.9\\n')\n\n            if any_device_connected:\n                self.status = 'C'\n\n\n    def on_unload(self, ui):\n        self.running = False\n        with ui._lock:\n            ui.remove_element('bluetooth')\n\n\n    def on_ui_setup(self, ui):\n        with ui._lock:\n            ui.add_element('bluetooth', LabeledValue(color=BLACK, label='BT', value='-', position=(ui.width() / 2 - 15, 0),\n                           label_font=fonts.Bold, text_font=fonts.Medium))\n\n\n    def on_ui_update(self, ui):\n        ui.set('bluetooth', self.status)\n"
  },
  {
    "path": "pwnagotchi/plugins/default/example.py",
    "content": "import logging\n\nimport pwnagotchi.plugins as plugins\nfrom pwnagotchi.ui.components import LabeledValue\nfrom pwnagotchi.ui.view import BLACK\nimport pwnagotchi.ui.fonts as fonts\n\n\nclass Example(plugins.Plugin):\n    __author__ = 'evilsocket@gmail.com'\n    __version__ = '1.0.0'\n    __license__ = 'GPL3'\n    __description__ = 'An example plugin for pwnagotchi that implements all the available callbacks.'\n\n    def __init__(self):\n        logging.debug(\"example plugin created\")\n\n    # called when http://<host>:<port>/plugins/<plugin>/ is called\n    # must return a html page\n    # IMPORTANT: If you use \"POST\"s, add a csrf-token (via csrf_token() and render_template_string)\n    def on_webhook(self, path, request):\n        pass\n\n    # called when the plugin is loaded\n    def on_loaded(self):\n        logging.warning(\"WARNING: this plugin should be disabled! options = \" % self.options)\n\n    # called before the plugin is unloaded\n    def on_unload(self, ui):\n        pass\n\n    # called hen there's internet connectivity\n    def on_internet_available(self, agent):\n        pass\n\n    # called to setup the ui elements\n    def on_ui_setup(self, ui):\n        # add custom UI elements\n        ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 - 25, 0),\n                                           label_font=fonts.Bold, text_font=fonts.Medium))\n\n    # called when the ui is updated\n    def on_ui_update(self, ui):\n        # update those elements\n        some_voltage = 0.1\n        some_capacity = 100.0\n        ui.set('ups', \"%4.2fV/%2i%%\" % (some_voltage, some_capacity))\n\n    # called when the hardware display setup is done, display is an hardware specific object\n    def on_display_setup(self, display):\n        pass\n\n    # called when everything is ready and the main loop is about to start\n    def on_ready(self, agent):\n        logging.info(\"unit is ready\")\n        # you can run custom bettercap commands if you want\n        #   agent.run('ble.recon on')\n        # or set a custom state\n        #   agent.set_bored()\n\n    # called when the AI finished loading\n    def on_ai_ready(self, agent):\n        pass\n\n    # called when the AI finds a new set of parameters\n    def on_ai_policy(self, agent, policy):\n        pass\n\n    # called when the AI starts training for a given number of epochs\n    def on_ai_training_start(self, agent, epochs):\n        pass\n\n    # called after the AI completed a training epoch\n    def on_ai_training_step(self, agent, _locals, _globals):\n        pass\n\n    # called when the AI has done training\n    def on_ai_training_end(self, agent):\n        pass\n\n    # called when the AI got the best reward so far\n    def on_ai_best_reward(self, agent, reward):\n        pass\n\n    # called when the AI got the worst reward so far\n    def on_ai_worst_reward(self, agent, reward):\n        pass\n\n    # called when a non overlapping wifi channel is found to be free\n    def on_free_channel(self, agent, channel):\n        pass\n\n    # called when the status is set to bored\n    def on_bored(self, agent):\n        pass\n\n    # called when the status is set to sad\n    def on_sad(self, agent):\n        pass\n\n    # called when the status is set to excited\n    def on_excited(self, agent):\n        pass\n\n    # called when the status is set to lonely\n    def on_lonely(self, agent):\n        pass\n\n    # called when the agent is rebooting the board\n    def on_rebooting(self, agent):\n        pass\n\n    # called when the agent is waiting for t seconds\n    def on_wait(self, agent, t):\n        pass\n\n    # called when the agent is sleeping for t seconds\n    def on_sleep(self, agent, t):\n        pass\n\n    # called when the agent refreshed its access points list\n    def on_wifi_update(self, agent, access_points):\n        pass\n\n    # called when the agent refreshed an unfiltered access point list\n    # this list contains all access points that were detected BEFORE filtering\n    def on_unfiltered_ap_list(self, agent, access_points):\n        pass\n\n    # called when the agent is sending an association frame\n    def on_association(self, agent, access_point):\n        pass\n\n    # called when the agent is deauthenticating a client station from an AP\n    def on_deauthentication(self, agent, access_point, client_station):\n        pass\n\n    # callend when the agent is tuning on a specific channel\n    def on_channel_hop(self, agent, channel):\n        pass\n\n    # called when a new handshake is captured, access_point and client_station are json objects\n    # if the agent could match the BSSIDs to the current list, otherwise they are just the strings of the BSSIDs\n    def on_handshake(self, agent, filename, access_point, client_station):\n        pass\n\n    # called when an epoch is over (where an epoch is a single loop of the main algorithm)\n    def on_epoch(self, agent, epoch, epoch_data):\n        pass\n\n    # called when a new peer is detected\n    def on_peer_detected(self, agent, peer):\n        pass\n\n    # called when a known peer is lost\n    def on_peer_lost(self, agent, peer):\n        pass\n"
  },
  {
    "path": "pwnagotchi/plugins/default/gpio_buttons.py",
    "content": "import logging\nimport RPi.GPIO as GPIO\nimport subprocess\nimport pwnagotchi.plugins as plugins\n\n\nclass GPIOButtons(plugins.Plugin):\n    __author__ = 'ratmandu@gmail.com'\n    __version__ = '1.0.0'\n    __license__ = 'GPL3'\n    __description__ = 'GPIO Button support plugin'\n\n    def __init__(self):\n        self.running = False\n        self.ports = {}\n        self.commands = None\n\n    def runCommand(self, channel):\n        command = self.ports[channel]\n        logging.info(f\"Button Pressed! Running command: {command}\")\n        process = subprocess.Popen(command, shell=True, stdin=None, stdout=open(\"/dev/null\", \"w\"), stderr=None,\n                                   executable=\"/bin/bash\")\n        process.wait()\n\n    def on_loaded(self):\n        logging.info(\"GPIO Button plugin loaded.\")\n\n        # get list of GPIOs\n        gpios = self.options['gpios']\n\n        # set gpio numbering\n        GPIO.setmode(GPIO.BCM)\n\n        for gpio, command in gpios.items():\n            gpio = int(gpio)\n            self.ports[gpio] = command\n            GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP)\n            GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runCommand, bouncetime=600)\n            logging.info(\"Added command: %s to GPIO #%d\", command, gpio)\n"
  },
  {
    "path": "pwnagotchi/plugins/default/gps.py",
    "content": "import json\nimport logging\nimport os\n\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.components import LabeledValue\nfrom pwnagotchi.ui.view import BLACK\n\n\nclass GPS(plugins.Plugin):\n    __author__ = \"evilsocket@gmail.com\"\n    __version__ = \"1.0.1\"\n    __license__ = \"GPL3\"\n    __description__ = \"Save GPS coordinates whenever an handshake is captured.\"\n\n    LINE_SPACING = 10\n    LABEL_SPACING = 0\n\n    def __init__(self):\n        self.running = False\n        self.coordinates = None\n\n    def on_loaded(self):\n        logging.info(f\"gps plugin loaded for {self.options['device']}\")\n\n    def on_ready(self, agent):\n        if os.path.exists(self.options[\"device\"]):\n            logging.info(\n                f\"enabling bettercap's gps module for {self.options['device']}\"\n            )\n            try:\n                agent.run(\"gps off\")\n            except Exception:\n                logging.info(f\"bettercap gps module was already off\")\n                pass\n\n            agent.run(f\"set gps.device {self.options['device']}\")\n            agent.run(f\"set gps.baudrate {self.options['speed']}\")\n            agent.run(\"gps on\")\n            logging.info(f\"bettercap gps module enabled on {self.options['device']}\")\n            self.running = True\n        else:\n            logging.warning(\"no GPS detected\")\n\n    def on_handshake(self, agent, filename, access_point, client_station):\n        if self.running:\n            info = agent.session()\n            self.coordinates = info[\"gps\"]\n            gps_filename = filename.replace(\".pcap\", \".gps.json\")\n\n            if self.coordinates and all([\n                # avoid 0.000... measurements\n                self.coordinates[\"Latitude\"], self.coordinates[\"Longitude\"]\n            ]):\n                logging.info(f\"saving GPS to {gps_filename} ({self.coordinates})\")\n                with open(gps_filename, \"w+t\") as fp:\n                    json.dump(self.coordinates, fp)\n            else:\n                logging.info(\"not saving GPS. Couldn't find location.\")\n\n    def on_ui_setup(self, ui):\n        try:\n            # Configure line_spacing\n            line_spacing = int(self.options['linespacing'])\n        except Exception:\n            # Set default value\n            line_spacing = self.LINE_SPACING\n\n        try:\n            # Configure position\n            pos = self.options['position'].split(',')\n            pos = [int(x.strip()) for x in pos]\n            lat_pos = (pos[0] + 5, pos[1])\n            lon_pos = (pos[0], pos[1] + line_spacing)\n            alt_pos = (pos[0] + 5, pos[1] + (2 * line_spacing))\n        except Exception:\n            # Set default value based on display type\n            if ui.is_waveshare_v2():\n                lat_pos = (127, 74)\n                lon_pos = (122, 84)\n                alt_pos = (127, 94)\n            elif ui.is_waveshare_v1():\n                lat_pos = (130, 70)\n                lon_pos = (125, 80)\n                alt_pos = (130, 90)\n            elif ui.is_inky():\n                lat_pos = (127, 60)\n                lon_pos = (122, 70)\n                alt_pos = (127, 80)\n            elif ui.is_waveshare144lcd():\n                # guessed values, add tested ones if you can\n                lat_pos = (67, 73)\n                lon_pos = (62, 83)\n                alt_pos = (67, 93)\n            elif ui.is_dfrobot_v2():\n                lat_pos = (127, 74)\n                lon_pos = (122, 84)\n                alt_pos = (127, 94)\n            elif ui.is_waveshare27inch():\n                lat_pos = (6, 120)\n                lon_pos = (1, 135)\n                alt_pos = (6, 150)\n            else:\n                # guessed values, add tested ones if you can\n                lat_pos = (127, 51)\n                lon_pos = (122, 61)\n                alt_pos = (127, 71)\n\n        ui.add_element(\n            \"latitude\",\n            LabeledValue(\n                color=BLACK,\n                label=\"lat:\",\n                value=\"-\",\n                position=lat_pos,\n                label_font=fonts.Small,\n                text_font=fonts.Small,\n                label_spacing=self.LABEL_SPACING,\n            ),\n        )\n        ui.add_element(\n            \"longitude\",\n            LabeledValue(\n                color=BLACK,\n                label=\"long:\",\n                value=\"-\",\n                position=lon_pos,\n                label_font=fonts.Small,\n                text_font=fonts.Small,\n                label_spacing=self.LABEL_SPACING,\n            ),\n        )\n        ui.add_element(\n            \"altitude\",\n            LabeledValue(\n                color=BLACK,\n                label=\"alt:\",\n                value=\"-\",\n                position=alt_pos,\n                label_font=fonts.Small,\n                text_font=fonts.Small,\n                label_spacing=self.LABEL_SPACING,\n            ),\n        )\n\n    def on_unload(self, ui):\n        with ui._lock:\n            ui.remove_element('latitude')\n            ui.remove_element('longitude')\n            ui.remove_element('altitude')\n\n    def on_ui_update(self, ui):\n        if self.coordinates and all([\n            # avoid 0.000... measurements\n            self.coordinates[\"Latitude\"], self.coordinates[\"Longitude\"]\n        ]):\n            # last char is sometimes not completely drawn ¯\\_(ツ)_/¯\n            # using an ending-whitespace as workaround on each line\n            ui.set(\"latitude\", f\"{self.coordinates['Latitude']:.4f} \")\n            ui.set(\"longitude\", f\"{self.coordinates['Longitude']:.4f} \")\n            ui.set(\"altitude\", f\"{self.coordinates['Altitude']:.1f}m \")\n"
  },
  {
    "path": "pwnagotchi/plugins/default/grid.py",
    "content": "import os\nimport logging\nimport time\nimport glob\nimport re\n\nimport pwnagotchi.grid as grid\nimport pwnagotchi.plugins as plugins\nfrom pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap\nfrom threading import Lock\n\n\ndef parse_pcap(filename):\n    logging.info(\"grid: parsing %s ...\" % filename)\n\n    net_id = os.path.basename(filename).replace('.pcap', '')\n\n    if '_' in net_id:\n        # /root/handshakes/ESSID_BSSID.pcap\n        essid, bssid = net_id.split('_')\n    else:\n        # /root/handshakes/BSSID.pcap\n        essid, bssid = '', net_id\n\n    mac_re = re.compile('[0-9a-fA-F]{12}')\n    if not mac_re.match(bssid):\n        return '', ''\n\n    it = iter(bssid)\n    bssid = ':'.join([a + b for a, b in zip(it, it)])\n\n    info = {\n        WifiInfo.ESSID: essid,\n        WifiInfo.BSSID: bssid,\n    }\n\n    try:\n        info = extract_from_pcap(filename, [WifiInfo.BSSID, WifiInfo.ESSID])\n    except Exception as e:\n        logging.error(\"grid: %s\" % e)\n\n    return info[WifiInfo.ESSID], info[WifiInfo.BSSID]\n\n\nclass Grid(plugins.Plugin):\n    __author__ = 'evilsocket@gmail.com'\n    __version__ = '1.0.1'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin signals the unit cryptographic identity and list of pwned networks and list of pwned ' \\\n                      'networks to api.pwnagotchi.ai '\n\n    def __init__(self):\n        self.options = dict()\n        self.report = StatusFile('/root/.api-report.json', data_format='json')\n\n        self.unread_messages = 0\n        self.total_messages = 0\n        self.lock = Lock()\n\n    def is_excluded(self, what):\n        for skip in self.options['exclude']:\n            skip = skip.lower()\n            what = what.lower()\n            if skip in what or skip.replace(':', '') in what:\n                return True\n        return False\n\n    def on_loaded(self):\n        logging.info(\"grid plugin loaded.\")\n\n    def set_reported(self, reported, net_id):\n        if net_id not in reported:\n            reported.append(net_id)\n        self.report.update(data={'reported': reported})\n\n    def check_inbox(self, agent):\n        logging.debug(\"checking mailbox ...\")\n        messages = grid.inbox()\n        self.total_messages = len(messages)\n        self.unread_messages = len([m for m in messages if m['seen_at'] is None])\n\n        if self.unread_messages:\n            plugins.on('unread_inbox', self.unread_messages)\n            logging.debug(\"[grid] unread:%d total:%d\" % (self.unread_messages, self.total_messages))\n            agent.view().on_unread_messages(self.unread_messages, self.total_messages)\n\n    def check_handshakes(self, agent):\n        logging.debug(\"checking pcaps\")\n\n        pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], \"*.pcap\"))\n        num_networks = len(pcap_files)\n        reported = self.report.data_field_or('reported', default=[])\n        num_reported = len(reported)\n        num_new = num_networks - num_reported\n\n        if num_new > 0:\n            if self.options['report']:\n                logging.info(\"grid: %d new networks to report\" % num_new)\n                logging.debug(\"self.options: %s\" % self.options)\n                logging.debug(\"  exclude: %s\" % self.options['exclude'])\n\n                for pcap_file in pcap_files:\n                    net_id = os.path.basename(pcap_file).replace('.pcap', '')\n                    if net_id not in reported:\n                        if self.is_excluded(net_id):\n                            logging.debug(\"skipping %s due to exclusion filter\" % pcap_file)\n                            self.set_reported(reported, net_id)\n                            continue\n\n                        essid, bssid = parse_pcap(pcap_file)\n                        if bssid:\n                            if self.is_excluded(essid) or self.is_excluded(bssid):\n                                logging.debug(\"not reporting %s due to exclusion filter\" % pcap_file)\n                                self.set_reported(reported, net_id)\n                            else:\n                                if grid.report_ap(essid, bssid):\n                                    self.set_reported(reported, net_id)\n                                time.sleep(1.5)\n                        else:\n                            logging.warning(\"no bssid found?!\")\n            else:\n                logging.debug(\"grid: reporting disabled\")\n\n    def on_internet_available(self, agent):\n        logging.debug(\"internet available\")\n\n        if self.lock.locked():\n            return\n\n        with self.lock:\n            try:\n                grid.update_data(agent.last_session)\n            except Exception as e:\n                logging.error(\"error connecting to the pwngrid-peer service: %s\" % e)\n                logging.debug(e, exc_info=True)\n                return\n\n            try:\n                self.check_inbox(agent)\n            except Exception as e:\n                logging.error(\"[grid] error while checking inbox: %s\" % e)\n                logging.debug(e, exc_info=True)\n\n            try:\n                self.check_handshakes(agent)\n            except Exception as e:\n                logging.error(\"[grid] error while checking pcaps: %s\" % e)\n                logging.debug(e, exc_info=True)\n"
  },
  {
    "path": "pwnagotchi/plugins/default/led.py",
    "content": "from threading import Event\nimport _thread\nimport logging\nimport time\n\nimport pwnagotchi.plugins as plugins\n\n\nclass Led(plugins.Plugin):\n    __author__ = 'evilsocket@gmail.com'\n    __version__ = '1.0.0'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin blinks the PWR led with different patterns depending on the event.'\n\n    def __init__(self):\n        self._is_busy = False\n        self._event = Event()\n        self._event_name = None\n        self._led_file = \"/sys/class/leds/led0/brightness\"\n        self._delay = 200\n\n    # called when the plugin is loaded\n    def on_loaded(self):\n        self._led_file = \"/sys/class/leds/led%d/brightness\" % self.options['led']\n        self._delay = int(self.options['delay'])\n\n        logging.info(\"[led] plugin loaded for %s\" % self._led_file)\n        self._on_event('loaded')\n        _thread.start_new_thread(self._worker, ())\n\n    def _on_event(self, event):\n        if not self._is_busy:\n            self._event_name = event\n            self._event.set()\n            logging.debug(\"[led] event '%s' set\", event)\n        else:\n            logging.debug(\"[led] skipping event '%s' because the worker is busy\", event)\n\n    def _led(self, on):\n        with open(self._led_file, 'wt') as fp:\n            fp.write(str(on))\n\n    def _blink(self, pattern):\n        logging.debug(\"[led] using pattern '%s' ...\" % pattern)\n        for c in pattern:\n            if c == ' ':\n                self._led(1)\n            else:\n                self._led(0)\n            time.sleep(self._delay / 1000.0)\n        # reset\n        self._led(0)\n\n    def _worker(self):\n        while True:\n            self._event.wait()\n            self._event.clear()\n            self._is_busy = True\n\n            try:\n                if self._event_name in self.options['patterns']:\n                    pattern = self.options['patterns'][self._event_name]\n                    self._blink(pattern)\n                else:\n                    logging.debug(\"[led] no pattern defined for %s\" % self._event_name)\n            except Exception as e:\n                logging.exception(\"[led] error while blinking\")\n\n            finally:\n                self._is_busy = False\n\n    # called when the unit is updating its software\n    def on_updating(self):\n        self._on_event('updating')\n\n    # called when there's one or more unread pwnmail messages\n    def on_unread_inbox(self, num_unread):\n        self._on_event('unread_inbox')\n\n    # called when there's internet connectivity\n    def on_internet_available(self, agent):\n        self._on_event('internet_available')\n\n    # called when everything is ready and the main loop is about to start\n    def on_ready(self, agent):\n        self._on_event('ready')\n\n    # called when the AI finished loading\n    def on_ai_ready(self, agent):\n        self._on_event('ai_ready')\n\n    # called when the AI starts training for a given number of epochs\n    def on_ai_training_start(self, agent, epochs):\n        self._on_event('ai_training_start')\n\n    # called when the AI got the best reward so far\n    def on_ai_best_reward(self, agent, reward):\n        self._on_event('ai_best_reward')\n\n    # called when the AI got the worst reward so far\n    def on_ai_worst_reward(self, agent, reward):\n        self._on_event('ai_worst_reward')\n\n    # called when the status is set to bored\n    def on_bored(self, agent):\n        self._on_event('bored')\n\n    # called when the status is set to sad\n    def on_sad(self, agent):\n        self._on_event('sad')\n\n    # called when the status is set to excited\n    def on_excited(self, agent):\n        self._on_event('excited')\n\n    # called when the status is set to lonely\n    def on_lonely(self, agent):\n        self._on_event('lonely')\n\n    # called when the agent is rebooting the board\n    def on_rebooting(self, agent):\n        self._on_event('rebooting')\n\n    # called when the agent is waiting for t seconds\n    def on_wait(self, agent, t):\n        self._on_event('wait')\n\n    # called when the agent is sleeping for t seconds\n    def on_sleep(self, agent, t):\n        self._on_event('sleep')\n\n    # called when the agent refreshed its access points list\n    def on_wifi_update(self, agent, access_points):\n        self._on_event('wifi_update')\n\n    # called when the agent is sending an association frame\n    def on_association(self, agent, access_point):\n        self._on_event('association')\n\n    # called when the agent is deauthenticating a client station from an AP\n    def on_deauthentication(self, agent, access_point, client_station):\n        self._on_event('deauthentication')\n\n    # called when a new handshake is captured, access_point and client_station are json objects\n    # if the agent could match the BSSIDs to the current list, otherwise they are just the strings of the BSSIDs\n    def on_handshake(self, agent, filename, access_point, client_station):\n        self._on_event('handshake')\n\n    # called when an epoch is over (where an epoch is a single loop of the main algorithm)\n    def on_epoch(self, agent, epoch, epoch_data):\n        self._on_event('epoch')\n\n    # called when a new peer is detected\n    def on_peer_detected(self, agent, peer):\n        self._on_event('peer_detected')\n\n    # called when a known peer is lost\n    def on_peer_lost(self, agent, peer):\n        self._on_event('peer_lost')\n"
  },
  {
    "path": "pwnagotchi/plugins/default/logtail.py",
    "content": "import os\nimport logging\nimport threading\nfrom itertools import islice\nfrom time import sleep\nfrom datetime import datetime,timedelta\nfrom pwnagotchi import plugins\nfrom pwnagotchi.utils import StatusFile\nfrom flask import render_template_string\nfrom flask import jsonify\nfrom flask import abort\nfrom flask import Response\n\n\nTEMPLATE = \"\"\"\n{% extends \"base.html\" %}\n{% set active_page = \"plugins\" %}\n{% block title %}\n    Logtail\n{% endblock %}\n\n{% block styles %}\n    {{ super() }}\n    <style>\n        * {\n            box-sizing: border-box;\n        }\n        #filter {\n            width: 100%;\n            font-size: 16px;\n            padding: 12px 20px 12px 40px;\n            border: 1px solid #ddd;\n            margin-bottom: 12px;\n        }\n        table {\n            border-collapse: collapse;\n            width: 100%;\n            border: 1px solid #ddd;\n        }\n        th, td {\n            text-align: left;\n            padding: 12px;\n            width: 1px;\n            white-space: nowrap;\n        }\n        td:nth-child(2) {\n            text-align: center;\n        }\n        thead, tr:hover {\n            background-color: #f1f1f1;\n        }\n        tr {\n            border-bottom: 1px solid #ddd;\n        }\n        div.sticky {\n            position: -webkit-sticky;\n            position: sticky;\n            top: 0;\n            display: table;\n            width: 100%;\n        }\n        div.sticky > * {\n            display: table-cell;\n        }\n        div.sticky > span {\n            width: 1%;\n        }\n        div.sticky > input {\n            width: 100%;\n        }\n        tr.default {\n            color: black;\n        }\n        tr.info {\n            color: black;\n        }\n        tr.warning {\n            color: darkorange;\n        }\n        tr.error {\n            color: crimson;\n        }\n        tr.debug {\n            color: blueviolet;\n        }\n        .ui-mobile .ui-page-active {\n            overflow: visible;\n            overflow-x: visible;\n        }\n    </style>\n{% endblock %}\n\n{% block script %}\n    var table = document.getElementById('table');\n    var filter = document.getElementById('filter');\n    var filterVal = filter.value.toUpperCase();\n\n    var xhr = new XMLHttpRequest();\n    xhr.open('GET', '{{ url_for('plugins') }}/logtail/stream');\n    xhr.send();\n    var position = 0;\n    var data;\n    var time;\n    var level;\n    var msg;\n    var colorClass;\n\n    function handleNewData() {\n        var messages = xhr.responseText.split('\\\\n');\n        filterVal = filter.value.toUpperCase();\n        messages.slice(position, -1).forEach(function(value) {\n\n            if (value.charAt(0) != '[') {\n                msg = value;\n                time = '';\n                level = '';\n            } else {\n                data = value.split(']');\n                time = data.shift() + ']';\n                level = data.shift() + ']';\n                msg = data.join(']');\n\n                switch(level) {\n                    case ' [INFO]':\n                        colorClass = 'info';\n                        break;\n                    case ' [WARNING]':\n                        colorClass = 'warning';\n                        break;\n                    case ' [ERROR]':\n                        colorClass = 'error';\n                        break;\n                    case ' [DEBUG]':\n                        colorClass = 'debug';\n                        break;\n                    default:\n                        colorClass = 'default';\n                        break;\n                }\n            }\n\n            var tr = document.createElement('tr');\n            var td1 = document.createElement('td');\n            var td2 = document.createElement('td');\n            var td3 = document.createElement('td');\n\n            td1.textContent = time;\n            td2.textContent = level;\n            td3.textContent = msg;\n\n            tr.appendChild(td1);\n            tr.appendChild(td2);\n            tr.appendChild(td3);\n\n            tr.className = colorClass;\n\n            if (filterVal.length > 0 && value.toUpperCase().indexOf(filterVal) == -1) {\n                tr.style.display = \"none\";\n            }\n\n            table.appendChild(tr);\n        });\n        position = messages.length - 1;\n    }\n\n    var scrollingElement = (document.scrollingElement || document.body)\n    function scrollToBottom () {\n       scrollingElement.scrollTop = scrollingElement.scrollHeight;\n    }\n\n    var timer;\n    var scrollElm = document.getElementById('autoscroll');\n    timer = setInterval(function() {\n        handleNewData();\n        if (scrollElm.checked) {\n            scrollToBottom();\n        }\n        if (xhr.readyState == XMLHttpRequest.DONE) {\n            clearInterval(timer);\n        }\n    }, 1000);\n\n    var typingTimer;\n    var doneTypingInterval = 1000;\n\n    filter.onkeyup = function() {\n        clearTimeout(typingTimer);\n        typingTimer = setTimeout(doneTyping, doneTypingInterval);\n    }\n\n    filter.onkeydown = function() {\n        clearTimeout(typingTimer);\n    }\n\n    function doneTyping() {\n        document.body.style.cursor = 'progress';\n        var tr, tds, td, i, txtValue;\n        filterVal = filter.value.toUpperCase();\n        tr = table.getElementsByTagName(\"tr\");\n        for (i = 1; i < tr.length; i++) {\n            txtValue = tr[i].textContent || tr[i].innerText;\n            if (txtValue.toUpperCase().indexOf(filterVal) > -1) {\n                tr[i].style.display = \"table-row\";\n            } else {\n                tr[i].style.display = \"none\";\n            }\n        }\n        document.body.style.cursor = 'default';\n    }\n{% endblock %}\n\n{% block content %}\n    <div class=\"sticky\">\n        <input type=\"text\" id=\"filter\" placeholder=\"Search for ...\" title=\"Type in a filter\">\n        <span><input checked type=\"checkbox\" id=\"autoscroll\"></span>\n        <span><label for=\"autoscroll\"> Autoscroll to bottom</label><br></span>\n    </div>\n    <table id=\"table\">\n        <thead>\n            <th>\n                Time\n            </th>\n            <th>\n                Level\n            </th>\n            <th>\n                Message\n            </th>\n        </thead>\n    </table>\n{% endblock %}\n\"\"\"\n\n\nclass Logtail(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '0.1.0'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin tails the logfile.'\n\n    def __init__(self):\n        self.lock = threading.Lock()\n        self.options = dict()\n        self.ready = False\n\n    def on_config_changed(self, config):\n        self.config = config\n        self.ready = True\n\n    def on_loaded(self):\n        \"\"\"\n        Gets called when the plugin gets loaded\n        \"\"\"\n        logging.info(\"Logtail plugin loaded.\")\n\n\n    def on_webhook(self, path, request):\n        if not self.ready:\n            return \"Plugin not ready\"\n\n        if not path or path == \"/\":\n            return render_template_string(TEMPLATE)\n\n        if path == 'stream':\n            def generate():\n                with open(self.config['main']['log']['path']) as f:\n                    yield ''.join(f.readlines()[-self.options.get('max-lines', 4096):])\n                    while True:\n                        yield f.readline()\n\n            return Response(generate(), mimetype='text/plain')\n\n        abort(404)\n"
  },
  {
    "path": "pwnagotchi/plugins/default/memtemp.py",
    "content": "# memtemp shows memory infos and cpu temperature\n#\n# mem usage, cpu load, cpu temp, cpu frequency\n#\n###############################################################\n#\n# Updated 18-10-2019 by spees <speeskonijn@gmail.com>\n# - Changed the place where the data was displayed on screen\n# - Made the data a bit more compact and easier to read\n# - removed the label so we wont waste screen space\n# - Updated version to 1.0.1\n#\n# 20-10-2019 by spees <speeskonijn@gmail.com>\n# - Refactored to use the already existing functions\n# - Now only shows memory usage in percentage\n# - Added CPU load\n# - Added horizontal and vertical orientation\n#\n# 19-09-2020 by crahan <crahan@n00.be>\n# - Added CPU frequency\n# - Made field types and order configurable (max 3 fields)\n# - Made line spacing and position configurable\n# - Updated code to dynamically generate UI elements\n# - Changed horizontal UI elements to Text\n# - Updated to version 1.0.2\n###############################################################\nfrom pwnagotchi.ui.components import LabeledValue, Text\nfrom pwnagotchi.ui.view import BLACK\nimport pwnagotchi.ui.fonts as fonts\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi\nimport logging\n\n\nclass MemTemp(plugins.Plugin):\n    __author__ = 'https://github.com/xenDE'\n    __version__ = '1.0.2'\n    __license__ = 'GPL3'\n    __description__ = 'A plugin that will display memory/cpu usage and temperature'\n\n    ALLOWED_FIELDS = {\n        'mem': 'mem_usage',\n        'cpu': 'cpu_load',\n        'temp': 'cpu_temp',\n        'freq': 'cpu_freq'\n    }\n    DEFAULT_FIELDS = ['mem', 'cpu', 'temp']\n    LINE_SPACING = 10\n    LABEL_SPACING = 0\n    FIELD_WIDTH = 4\n\n    def on_loaded(self):\n        logging.info(\"memtemp plugin loaded.\")\n\n    def mem_usage(self):\n        return f\"{int(pwnagotchi.mem_usage() * 100)}%\"\n\n    def cpu_load(self):\n        return f\"{int(pwnagotchi.cpu_load() * 100)}%\"\n\n    def cpu_temp(self):\n        if self.options['scale'] == \"fahrenheit\":\n            temp = (pwnagotchi.temperature() * 9 / 5) + 32\n            symbol = \"f\"\n        elif self.options['scale'] == \"kelvin\":\n            temp = pwnagotchi.temperature() + 273.15\n            symbol = \"k\"\n        else:\n            # default to celsius\n            temp = pwnagotchi.temperature()\n            symbol = \"c\"\n        return f\"{temp}{symbol}\"\n\n    def cpu_freq(self):\n        with open('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq', 'rt') as fp:\n            return f\"{round(float(fp.readline())/1000000, 1)}G\"\n\n    def pad_text(self, data):\n        return \" \" * (self.FIELD_WIDTH - len(data)) + data\n\n    def on_ui_setup(self, ui):\n        try:\n            # Configure field list\n            self.fields = self.options['fields'].split(',')\n            self.fields = [x.strip() for x in self.fields if x.strip() in self.ALLOWED_FIELDS.keys()]\n            self.fields = self.fields[:3]  # limit to the first 3 fields\n        except Exception:\n            # Set default value\n            self.fields = self.DEFAULT_FIELDS\n\n        try:\n            # Configure line_spacing\n            line_spacing = int(self.options['linespacing'])\n        except Exception:\n            # Set default value\n            line_spacing = self.LINE_SPACING\n\n        try:\n            # Configure position\n            pos = self.options['position'].split(',')\n            pos = [int(x.strip()) for x in pos]\n            if self.options['orientation'] == \"vertical\":\n                v_pos = (pos[0], pos[1])\n            else:\n                h_pos = (pos[0], pos[1])\n        except Exception:\n            # Set default position based on screen type\n            if ui.is_waveshare_v2():\n                h_pos = (178, 84)\n                v_pos = (197, 74)\n            elif ui.is_waveshare_v1():\n                h_pos = (170, 80)\n                v_pos = (165, 61)\n            elif ui.is_waveshare144lcd():\n                h_pos = (53, 77)\n                v_pos = (73, 67)\n            elif ui.is_inky():\n                h_pos = (140, 68)\n                v_pos = (160, 54)\n            elif ui.is_waveshare27inch():\n                h_pos = (192, 138)\n                v_pos = (211, 122)\n            else:\n                h_pos = (155, 76)\n                v_pos = (175, 61)\n\n        if self.options['orientation'] == \"vertical\":\n            # Dynamically create the required LabeledValue objects\n            for idx, field in enumerate(self.fields):\n                v_pos_x = v_pos[0]\n                v_pos_y = v_pos[1] + ((len(self.fields) - 3) * -1 * line_spacing)\n                ui.add_element(\n                    f\"memtemp_{field}\",\n                    LabeledValue(\n                        color=BLACK,\n                        label=f\"{self.pad_text(field)}:\",\n                        value=\"-\",\n                        position=(v_pos_x, v_pos_y + (idx * line_spacing)),\n                        label_font=fonts.Small,\n                        text_font=fonts.Small,\n                        label_spacing=self.LABEL_SPACING,\n                    )\n                )\n        else:\n            # default to horizontal\n            h_pos_x = h_pos[0] + ((len(self.fields) - 3) * -1 * 25)\n            h_pos_y = h_pos[1]\n            ui.add_element(\n                'memtemp_header',\n                Text(\n                    color=BLACK,\n                    value=\" \".join([self.pad_text(x) for x in self.fields]),\n                    position=(h_pos_x, h_pos_y),\n                    font=fonts.Small,\n                )\n            )\n            ui.add_element(\n                'memtemp_data',\n                Text(\n                    color=BLACK,\n                    value=\" \".join([self.pad_text(\"-\") for x in self.fields]),\n                    position=(h_pos_x, h_pos_y + line_spacing),\n                    font=fonts.Small,\n                )\n            )\n\n    def on_unload(self, ui):\n        with ui._lock:\n            if self.options['orientation'] == \"vertical\":\n                for idx, field in enumerate(self.fields):\n                    ui.remove_element(f\"memtemp_{field}\")\n            else:\n                # default to horizontal\n                ui.remove_element('memtemp_header')\n                ui.remove_element('memtemp_data')\n\n    def on_ui_update(self, ui):\n        if self.options['orientation'] == \"vertical\":\n            for idx, field in enumerate(self.fields):\n                ui.set(f\"memtemp_{field}\", getattr(self, self.ALLOWED_FIELDS[field])())\n        else:\n            # default to horizontal\n            data = \" \".join([self.pad_text(getattr(self, self.ALLOWED_FIELDS[x])()) for x in self.fields])\n            ui.set('memtemp_data', data)\n"
  },
  {
    "path": "pwnagotchi/plugins/default/net-pos.py",
    "content": "import logging\nimport json\nimport os\nimport threading\nimport requests\nimport time\nimport pwnagotchi.plugins as plugins\nfrom pwnagotchi.utils import StatusFile\n\n\nclass NetPos(plugins.Plugin):\n    __author__ = 'zenzen san'\n    __version__ = '2.0.3'\n    __license__ = 'GPL3'\n    __description__ = \"\"\"Saves a json file with the access points with more signal\n                         whenever a handshake is captured.\n                         When internet is available the files are converted in geo locations\n                         using Mozilla LocationService \"\"\"\n\n    API_URL = 'https://location.services.mozilla.com/v1/geolocate?key={api}'\n\n    def __init__(self):\n        self.report = StatusFile('/root/.net_pos_saved', data_format='json')\n        self.skip = list()\n        self.ready = False\n        self.lock = threading.Lock()\n\n    def on_loaded(self):\n        if 'api_key' not in self.options or ('api_key' in self.options and not self.options['api_key']):\n            logging.error(\"NET-POS: api_key isn't set. Can't use mozilla's api.\")\n            return\n        if 'api_url' in self.options:\n            self.API_URL = self.options['api_url']\n        self.ready = True\n        logging.info(\"net-pos plugin loaded.\")\n        logging.debug(f\"net-pos: use api_url: {self.API_URL}\");\n\n    def _append_saved(self, path):\n        to_save = list()\n        if isinstance(path, str):\n            to_save.append(path)\n        elif isinstance(path, list):\n            to_save += path\n        else:\n            raise TypeError(\"Expected list or str, got %s\" % type(path))\n\n        with open('/root/.net_pos_saved', 'a') as saved_file:\n            for x in to_save:\n                saved_file.write(x + \"\\n\")\n\n    def on_internet_available(self, agent):\n        if self.lock.locked():\n            return\n        with self.lock:\n            if self.ready:\n                config = agent.config()\n                display = agent.view()\n                reported = self.report.data_field_or('reported', default=list())\n                handshake_dir = config['bettercap']['handshakes']\n\n                all_files = os.listdir(handshake_dir)\n                all_np_files = [os.path.join(handshake_dir, filename)\n                                for filename in all_files\n                                if filename.endswith('.net-pos.json')]\n                new_np_files = set(all_np_files) - set(reported) - set(self.skip)\n\n                if new_np_files:\n                    logging.debug(\"NET-POS: Found %d new net-pos files. Fetching positions ...\", len(new_np_files))\n                    display.set('status', f\"Found {len(new_np_files)} new net-pos files. Fetching positions ...\")\n                    display.update(force=True)\n                    for idx, np_file in enumerate(new_np_files):\n\n                        geo_file = np_file.replace('.net-pos.json', '.geo.json')\n                        if os.path.exists(geo_file):\n                            # got already the position\n                            reported.append(np_file)\n                            self.report.update(data={'reported': reported})\n                            continue\n\n                        try:\n                            geo_data = self._get_geo_data(np_file)  # returns json obj\n                        except requests.exceptions.RequestException as req_e:\n                            logging.error(\"NET-POS: %s - RequestException: %s\", np_file, req_e)\n                            self.skip += np_file\n                            continue\n                        except json.JSONDecodeError as js_e:\n                            logging.error(\"NET-POS: %s - JSONDecodeError: %s, removing it...\", np_file, js_e)\n                            os.remove(np_file)\n                            continue\n                        except OSError as os_e:\n                            logging.error(\"NET-POS: %s - OSError: %s\", np_file, os_e)\n                            self.skip += np_file\n                            continue\n\n                        with open(geo_file, 'w+t') as sf:\n                            json.dump(geo_data, sf)\n\n                        reported.append(np_file)\n                        self.report.update(data={'reported': reported})\n\n                        display.set('status', f\"Fetching positions ({idx + 1}/{len(new_np_files)})\")\n                        display.update(force=True)\n\n    def on_handshake(self, agent, filename, access_point, client_station):\n        netpos = self._get_netpos(agent)\n        if not netpos['wifiAccessPoints']:\n            return\n\n        netpos[\"ts\"] = int(\"%.0f\" % time.time())\n        netpos_filename = filename.replace('.pcap', '.net-pos.json')\n        logging.debug(\"NET-POS: Saving net-location to %s\", netpos_filename)\n\n        try:\n            with open(netpos_filename, 'w+t') as net_pos_file:\n                json.dump(netpos, net_pos_file)\n        except OSError as os_e:\n            logging.error(\"NET-POS: %s\", os_e)\n\n\n    def _get_netpos(self, agent):\n        aps = agent.get_access_points()\n        netpos = dict()\n        netpos['wifiAccessPoints'] = list()\n        # 6 seems a good number to save a wifi networks location\n        for access_point in sorted(aps, key=lambda i: i['rssi'], reverse=True)[:6]:\n            netpos['wifiAccessPoints'].append({'macAddress': access_point['mac'],\n                                               'signalStrength': access_point['rssi']})\n        return netpos\n\n    def _get_geo_data(self, path, timeout=30):\n        geourl = self.API_URL.format(api=self.options['api_key'])\n\n        try:\n            with open(path, \"r\") as json_file:\n                data = json.load(json_file)\n        except json.JSONDecodeError as js_e:\n            raise js_e\n        except OSError as os_e:\n            raise os_e\n\n        try:\n            result = requests.post(geourl,\n                                   json=data,\n                                   timeout=timeout)\n            return_geo = result.json()\n            if data[\"ts\"]:\n                return_geo[\"ts\"] = data[\"ts\"]\n            return return_geo\n        except requests.exceptions.RequestException as req_e:\n            raise req_e\n"
  },
  {
    "path": "pwnagotchi/plugins/default/onlinehashcrack.py",
    "content": "import os\nimport csv\nimport logging\nimport re\nimport requests\nfrom datetime import datetime\nfrom threading import Lock\nfrom pwnagotchi.utils import StatusFile, remove_whitelisted\nimport pwnagotchi.plugins as plugins\nfrom json.decoder import JSONDecodeError\n\n\nclass OnlineHashCrack(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '2.1.0'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin automatically uploads handshakes to https://onlinehashcrack.com'\n\n    def __init__(self):\n        self.ready = False\n        try:\n            self.report = StatusFile('/root/.ohc_uploads', data_format='json')\n        except JSONDecodeError:\n            os.remove('/root/.ohc_uploads')\n            self.report = StatusFile('/root/.ohc_uploads', data_format='json')\n        self.skip = list()\n        self.lock = Lock()\n\n    def on_loaded(self):\n        \"\"\"\n        Gets called when the plugin gets loaded\n        \"\"\"\n        if 'email' not in self.options or ('email' in self.options and not self.options['email']):\n            logging.error(\"OHC: Email isn't set. Can't upload to onlinehashcrack.com\")\n            return\n\n        if 'whitelist' not in self.options:\n            self.options['whitelist'] = list()\n\n        self.ready = True\n        logging.info(\"OHC: OnlineHashCrack plugin loaded.\")\n\n\n    def _upload_to_ohc(self, path, timeout=30):\n        \"\"\"\n        Uploads the file to onlinehashcrack.com\n        \"\"\"\n        with open(path, 'rb') as file_to_upload:\n            data = {'email': self.options['email']}\n            payload = {'file': file_to_upload}\n\n            try:\n                result = requests.post('https://api.onlinehashcrack.com',\n                                       data=data,\n                                       files=payload,\n                                       timeout=timeout)\n                if 'already been sent' in result.text:\n                    logging.debug(f\"{path} was already uploaded.\")\n            except requests.exceptions.RequestException as e:\n                logging.debug(f\"OHC: Got an exception while uploading {path} -> {e}\")\n                raise e\n\n    def _download_cracked(self, save_file, timeout=120):\n        \"\"\"\n        Downloads the cracked passwords and saves them\n\n        returns the number of downloaded passwords\n        \"\"\"\n        try:\n            s = requests.Session()\n            dashboard = s.get(self.options['dashboard'], timeout=timeout)\n            result = s.get('https://www.onlinehashcrack.com/wpa-exportcsv', timeout=timeout)\n            result.raise_for_status()\n            with open(save_file, 'wb') as output_file:\n                output_file.write(result.content)\n        except requests.exceptions.RequestException as req_e:\n            raise req_e\n        except OSError as os_e:\n            raise os_e\n\n\n    def on_webhook(self, path, request):\n        import requests\n        from flask import redirect\n        s = requests.Session()\n        s.get('https://www.onlinehashcrack.com/dashboard')\n        r = s.post('https://www.onlinehashcrack.com/dashboard', data={'emailTasks': self.options['email'], 'submit': ''})\n        return redirect(r.url, code=302)\n\n\n    def on_internet_available(self, agent):\n        \"\"\"\n        Called in manual mode when there's internet connectivity\n        \"\"\"\n\n        if not self.ready or self.lock.locked():\n            return\n\n        with self.lock:\n            display = agent.view()\n            config = agent.config()\n            reported = self.report.data_field_or('reported', default=list())\n            handshake_dir = config['bettercap']['handshakes']\n            handshake_filenames = os.listdir(handshake_dir)\n            handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if\n                               filename.endswith('.pcap')]\n            # pull out whitelisted APs\n            handshake_paths = remove_whitelisted(handshake_paths, self.options['whitelist'])\n            handshake_new = set(handshake_paths) - set(reported) - set(self.skip)\n            if handshake_new:\n                logging.info(\"OHC: Internet connectivity detected. Uploading new handshakes to onlinehashcrack.com\")\n                for idx, handshake in enumerate(handshake_new):\n                    display.on_uploading(f\"onlinehashcrack.com ({idx + 1}/{len(handshake_new)})\")\n\n                    try:\n                        self._upload_to_ohc(handshake)\n                        if handshake not in reported:\n                            reported.append(handshake)\n                            self.report.update(data={'reported': reported})\n                            logging.debug(f\"OHC: Successfully uploaded {handshake}\")\n                    except requests.exceptions.RequestException as req_e:\n                        self.skip.append(handshake)\n                        logging.debug(\"OHC: %s\", req_e)\n                        continue\n                    except OSError as os_e:\n                        self.skip.append(handshake)\n                        logging.debug(\"OHC: %s\", os_e)\n                        continue\n\n                display.on_normal()\n\n            if 'dashboard' in self.options and self.options['dashboard']:\n                cracked_file = os.path.join(handshake_dir, 'onlinehashcrack.cracked')\n                if os.path.exists(cracked_file):\n                    last_check = datetime.fromtimestamp(os.path.getmtime(cracked_file))\n                    if last_check is not None and ((datetime.now() - last_check).seconds / (60 * 60)) < 1:\n                        return\n                try:\n                    self._download_cracked(cracked_file)\n                    logging.info(\"OHC: Downloaded cracked passwords.\")\n                except requests.exceptions.RequestException as req_e:\n                    logging.debug(\"OHC: %s\", req_e)\n                except OSError as os_e:\n                    logging.debug(\"OHC: %s\", os_e)\n                if 'single_files' in self.options and self.options['single_files']:\n                    with open(cracked_file, 'r') as cracked_list:\n                        for row in csv.DictReader(cracked_list):\n                            if row['password']:\n                                filename = re.sub(r'[^a-zA-Z0-9]', '', row['ESSID']) + '_' + row['BSSID'].replace(':','')\n                                if os.path.exists( os.path.join(handshake_dir, filename+'.pcap') ):\n                                    with open(os.path.join(handshake_dir, filename+'.pcap.cracked'), 'w') as f:\n                                        f.write(row['password'])\n"
  },
  {
    "path": "pwnagotchi/plugins/default/paw-gps.py",
    "content": "import logging\nimport requests\nimport pwnagotchi.plugins as plugins\n\n'''\nYou need an bluetooth connection to your android phone which is running PAW server with the GPS \"hack\" from Systemik and edited by shaynemk\nGUIDE HERE: https://community.pwnagotchi.ai/t/setting-up-paw-gps-on-android\n'''\n\n\nclass PawGPS(plugins.Plugin):\n    __author__ = 'leont'\n    __version__ = '1.0.1'\n    __name__ = 'pawgps'\n    __license__ = 'GPL3'\n    __description__ = 'Saves GPS coordinates whenever an handshake is captured. The GPS data is get from PAW on android.'\n\n    def on_loaded(self):\n        logging.info(\"[paw-gps] plugin loaded\")\n        if 'ip' not in self.options or ('ip' in self.options and self.options['ip'] is None) or (len('ip' in self.options and self.options['ip']) is 0):\n            logging.info(\"[paw-gps] no IP Address defined in the config file, will uses paw server default (192.168.44.1:8080)\")\n\n    def on_handshake(self, agent, filename, access_point, client_station):\n        if 'ip' not in self.options or ('ip' in self.options and self.options['ip'] is None or (len('ip' in self.options and self.options['ip']) is 0)):\n            ip = \"192.168.44.1:8080\"\n        else:\n            ip = self.options['ip']\n\n        try:\n            gps = requests.get('http://' + ip + '/gps.xhtml')\n            try:\n                gps_filename = filename.replace('.pcap', '.paw-gps.json')\n                logging.info(\"[paw-gps] saving GPS data to %s\" % (gps_filename))\n                with open(gps_filename, 'w+t') as f:\n                    f.write(gps.text)\n            except Exception as error:\n                logging.error(f\"[paw-gps] encountered error while saving gps data: {error}\")\n        except Exception as error:\n            logging.error(f\"[paw-gps] encountered error while getting gps data: {error}\")\n"
  },
  {
    "path": "pwnagotchi/plugins/default/session-stats.py",
    "content": "import os\nimport logging\nimport threading\nfrom time import sleep\nfrom datetime import datetime,timedelta\nfrom pwnagotchi import plugins\nfrom pwnagotchi.utils import StatusFile\nfrom flask import render_template_string\nfrom flask import jsonify\n\nTEMPLATE = \"\"\"\n{% extends \"base.html\" %}\n{% set active_page = \"plugins\" %}\n{% block title %}\n    Session stats\n{% endblock %}\n\n{% block styles %}\n    {{ super() }}\n    <link rel=\"stylesheet\" href=\"/css/jquery.jqplot.min.css\"/>\n    <link rel=\"stylesheet\" href=\"/css/jquery.jqplot.css\"/>\n    <style>\n        div.chart {\n            height: 400px;\n            width: 100%;\n        }\n        div#session {\n            width: 100%;\n        }\n    </style>\n{% endblock %}\n\n{% block scripts %}\n    {{ super() }}\n     <script type=\"text/javascript\" src=\"/js/jquery.jqplot.min.js\"></script>\n     <script type=\"text/javascript\" src=\"/js/jquery.jqplot.js\"></script>\n     <script type=\"text/javascript\" src=\"/js/plugins/jqplot.mobile.js\"></script>\n     <script type=\"text/javascript\" src=\"/js/plugins/jqplot.json2.js\"></script>\n     <script type=\"text/javascript\" src=\"/js/plugins/jqplot.dateAxisRenderer.js\"></script>\n     <script type=\"text/javascript\" src=\"/js/plugins/jqplot.highlighter.js\"></script>\n     <script type=\"text/javascript\" src=\"/js/plugins/jqplot.cursor.js\"></script>\n     <script type=\"text/javascript\" src=\"/js/plugins/jqplot.enhancedLegendRenderer.js\"></script>\n{% endblock %}\n\n{% block script %}\n    $(document).ready(function(){\n        var ajaxDataRenderer = function(url, plot, options) {\n        var ret = null;\n        $.ajax({\n            async: false,\n            url: url,\n            dataType:\"json\",\n            success: function(data) {\n                ret = data;\n            }\n        });\n        return ret;\n        };\n\n    function loadFiles(url, elm) {\n        var data = ajaxDataRenderer(url);\n        var x = document.getElementById(elm);\n        $.each(data['files'], function( index, value ) {\n            var option = document.createElement(\"option\");\n            option.text = value;\n            x.add(option);\n        });\n    }\n\n    function loadData(url, elm, title, fill) {\n        var data = ajaxDataRenderer(url);\n        var plot_os = $.jqplot(elm, data.values,{\n        title: title,\n        stackSeries: fill,\n        seriesDefaults: {\n            showMarker: !fill,\n            fill: fill,\n            fillAndStroke: fill\n        },\n        legend: {\n            show: true,\n            renderer: $.jqplot.EnhancedLegendRenderer,\n            placement: 'outsideGrid',\n            labels: data.labels,\n            location: 's',\n            rendererOptions: {\n                numberRows: '2',\n            },\n            rowSpacing: '0px'\n        },\n        axes:{\n            xaxis:{\n                renderer:$.jqplot.DateAxisRenderer,\n                tickOptions:{formatString:'%H:%M:%S'}\n            },\n            yaxis:{\n                tickOptions:{formatString:'%.2f'}\n            }\n        },\n        highlighter: {\n            show: true,\n            sizeAdjust: 7.5\n        },\n        cursor:{\n            show: true,\n            tooltipLocation:'sw'\n        }\n        }).replot({\n        axes:{\n            xaxis:{\n                renderer:$.jqplot.DateAxisRenderer,\n                tickOptions:{formatString:'%H:%M:%S'}\n            },\n            yaxis:{\n                tickOptions:{formatString:'%.2f'}\n            }\n        }\n        });\n    }\n\n    function loadSessionFiles() {\n        loadFiles('/plugins/session-stats/session', 'session');\n        $(\"#session\").change(function() {\n            loadSessionData();\n        });\n    }\n\n    function loadSessionData() {\n        var x = document.getElementById(\"session\");\n        var session = x.options[x.selectedIndex].text;\n        loadData('/plugins/session-stats/os' + '?session=' + session, 'chart_os', 'OS', false)\n        loadData('/plugins/session-stats/temp' + '?session=' + session, 'chart_temp', 'Temp', false)\n        loadData('/plugins/session-stats/wifi' + '?session=' + session, 'chart_wifi', 'Wifi', true)\n        loadData('/plugins/session-stats/duration' + '?session=' + session, 'chart_duration', 'Sleeping', true)\n        loadData('/plugins/session-stats/reward' + '?session=' + session, 'chart_reward', 'Reward', false)\n        loadData('/plugins/session-stats/epoch' + '?session=' + session, 'chart_epoch', 'Epochs', false)\n    }\n\n\n    loadSessionFiles();\n    loadSessionData();\n    setInterval(loadSessionData, 60000);\n    });\n{% endblock %}\n\n{% block content %}\n    <select id=\"session\">\n        <option selected>Current</option>\n    </select>\n    <div id=\"chart_os\" class=\"chart\"></div>\n    <div id=\"chart_temp\" class=\"chart\"></div>\n    <div id=\"chart_wifi\" class=\"chart\"></div>\n    <div id=\"chart_duration\" class=\"chart\"></div>\n    <div id=\"chart_reward\" class=\"chart\"></div>\n    <div id=\"chart_epoch\" class=\"chart\"></div>\n{% endblock %}\n\"\"\"\n\nclass GhettoClock:\n    def __init__(self):\n        self.lock = threading.Lock()\n        self._track = datetime.now()\n        self._counter_thread = threading.Thread(target=self.counter)\n        self._counter_thread.daemon = True\n        self._counter_thread.start()\n\n    def counter(self):\n        while True:\n            with self.lock:\n                self._track += timedelta(seconds=1)\n            sleep(1)\n\n    def now(self):\n        with self.lock:\n            return self._track\n\n\nclass SessionStats(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '0.1.0'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin displays stats of the current session.'\n\n    def __init__(self):\n        self.lock = threading.Lock()\n        self.options = dict()\n        self.stats = dict()\n        self.clock = GhettoClock()\n\n    def on_loaded(self):\n        \"\"\"\n        Gets called when the plugin gets loaded\n        \"\"\"\n        # this has to happen in \"loaded\" because the options are not yet\n        # available in the __init__\n        os.makedirs(self.options['save_directory'], exist_ok=True)\n        self.session_name = \"stats_{}.json\".format(self.clock.now().strftime(\"%Y_%m_%d_%H_%M\"))\n        self.session = StatusFile(os.path.join(self.options['save_directory'],\n                                               self.session_name),\n                                  data_format='json')\n        logging.info(\"Session-stats plugin loaded.\")\n\n    def on_epoch(self, agent, epoch, epoch_data):\n        \"\"\"\n        Save the epoch_data to self.stats\n        \"\"\"\n        with self.lock:\n            self.stats[self.clock.now().strftime(\"%H:%M:%S\")] = epoch_data\n            self.session.update(data={'data': self.stats})\n\n    @staticmethod\n    def extract_key_values(data, subkeys):\n        result = dict()\n        result['values'] = list()\n        result['labels'] = subkeys\n        for plot_key in subkeys:\n            v = [ [ts,d[plot_key]] for ts, d in data.items()]\n            result['values'].append(v)\n        return result\n\n    def on_webhook(self, path, request):\n        if not path or path == \"/\":\n            return render_template_string(TEMPLATE)\n\n        session_param = request.args.get('session')\n\n        if path == \"os\":\n            extract_keys = ['cpu_load','mem_usage',]\n        elif path == \"temp\":\n            extract_keys = ['temperature']\n        elif path == \"wifi\":\n            extract_keys = [\n                'missed_interactions',\n                'num_hops',\n                'num_peers',\n                'tot_bond',\n                'avg_bond',\n                'num_deauths',\n                'num_associations',\n                'num_handshakes',\n            ]\n        elif path == \"duration\":\n            extract_keys = [\n                'duration_secs',\n                'slept_for_secs',\n            ]\n        elif path == \"reward\":\n            extract_keys = [\n                'reward',\n            ]\n        elif path == \"epoch\":\n            extract_keys = [\n                'active_for_epochs',\n            ]\n        elif path == \"session\":\n            return jsonify({'files': os.listdir(self.options['save_directory'])})\n\n        with self.lock:\n            data = self.stats\n            if session_param and session_param != 'Current':\n                file_stats = StatusFile(os.path.join(self.options['save_directory'], session_param), data_format='json')\n                data = file_stats.data_field_or('data', default=dict())\n            return jsonify(SessionStats.extract_key_values(data, extract_keys))\n"
  },
  {
    "path": "pwnagotchi/plugins/default/switcher.py",
    "content": "import os\nimport logging\nfrom threading import Lock\nfrom functools import partial\nfrom pwnagotchi import plugins\nfrom pwnagotchi import reboot\n\n\ndef systemd_dropin(name, content):\n    if not name.endswith('.service'):\n        name = '%s.service' % name\n\n    dropin_dir = \"/etc/systemd/system/%s.d/\" % name\n    os.makedirs(dropin_dir, exist_ok=True)\n\n    with open(os.path.join(dropin_dir, \"switcher.conf\"), \"wt\") as dropin:\n        dropin.write(content)\n\n    systemctl(\"daemon-reload\")\n\ndef systemctl(command, unit=None):\n    if unit:\n        os.system(\"/bin/systemctl %s %s\" % (command, unit))\n    else:\n        os.system(\"/bin/systemctl %s\" % command)\n\ndef run_task(name, options):\n    task_service_name = \"switcher-%s-task.service\" % name\n    # save all the commands to a shell script\n    script_dir = '/usr/local/bin/'\n    script_path = os.path.join(script_dir, 'switcher-%s.sh' % name)\n    os.makedirs(script_dir, exist_ok=True)\n\n    with open(script_path, 'wt') as script_file:\n        script_file.write('#!/bin/bash\\n')\n        for cmd in options['commands']:\n            script_file.write('%s\\n' % cmd)\n\n    os.system(\"chmod a+x %s\" % script_path)\n\n    # here we create the service which runs the tasks\n    with open('/etc/systemd/system/%s' % task_service_name, 'wt') as task_service:\n        task_service.write(\"\"\"\n        [Unit]\n        Description=Executes the tasks of the pwnagotchi switcher plugin\n        After=pwnagotchi.service bettercap.service\n\n        [Service]\n        Type=oneshot\n        RemainAfterExit=yes\n        ExecStart=-/usr/local/bin/switcher-%s.sh\n        ExecStart=-/bin/rm /etc/systemd/system/%s\n        ExecStart=-/bin/rm /usr/local/bin/switcher-%s.sh\n\n        [Install]\n        WantedBy=multi-user.target\n        \"\"\" % (name, task_service_name, name))\n\n    if 'reboot' in options and options['reboot']:\n        # create a indication file!\n        # if this file is set, we want the switcher-tasks to run\n        open('/root/.switcher', 'a').close()\n\n        # add condition\n        systemd_dropin(\"pwnagotchi.service\", \"\"\"\n        [Unit]\n        ConditionPathExists=!/root/.switcher\"\"\")\n\n        systemd_dropin(\"bettercap.service\", \"\"\"\n        [Unit]\n        ConditionPathExists=!/root/.switcher\"\"\")\n\n        systemd_dropin(task_service_name, \"\"\"\n        [Service]\n        ExecStart=-/bin/rm /root/.switcher\n        ExecStart=-/bin/rm /etc/systemd/system/switcher-reboot.timer\"\"\")\n\n        with open('/etc/systemd/system/switcher-reboot.timer', 'wt') as reboot_timer:\n            reboot_timer.write(\"\"\"\n            [Unit]\n            Description=Reboot when time is up\n            ConditionPathExists=/root/.switcher\n\n            [Timer]\n            OnBootSec=%sm\n            Unit=reboot.target\n\n            [Install]\n            WantedBy=timers.target\n            \"\"\" % options['stopwatch'])\n\n        systemctl(\"daemon-reload\")\n        systemctl(\"enable\", \"switcher-reboot.timer\")\n        systemctl(\"enable\", task_service_name)\n        reboot()\n        return\n\n    systemctl(\"daemon-reload\")\n    systemctl(\"start\", task_service_name)\n\nclass Switcher(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '0.0.1'\n    __name__ = 'switcher'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin is a generic task scheduler.'\n\n    def __init__(self):\n        self.ready = False\n        self.lock = Lock()\n\n    def trigger(self, name, *args, **kwargs):\n        with self.lock:\n            function_name = name.lstrip('on_')\n            if function_name in self.tasks:\n                task = self.tasks[function_name]\n\n                # is this task enabled?\n                if 'enabled' not in task or ('enabled' in task and not task['enabled']):\n                    return\n\n                run_task(function_name, task)\n\n    def on_loaded(self):\n        if 'tasks' in self.options and self.options['tasks']:\n            self.tasks = self.options['tasks']\n        else:\n            logging.debug('[switcher] No tasks found...')\n            return\n\n        logging.info(\"[switcher] is loaded.\")\n\n        # create hooks\n        logging.debug(\"[switcher] creating hooks...\")\n        methods = ['webhook', 'internet_available', 'ui_setup', 'ui_update',\n                   'unload', 'display_setup', 'ready', 'ai_ready', 'ai_policy',\n                   'ai_training_start', 'ai_training_step', 'ai_training_end',\n                   'ai_best_reward', 'ai_worst_reward', 'free_channel',\n                   'bored', 'sad', 'excited', 'lonely', 'rebooting', 'wait',\n                   'sleep', 'wifi_update', 'unfiltered_ap_list', 'association',\n                   'deauthentication', 'channel_hop', 'handshake', 'epoch',\n                   'peer_detected', 'peer_lost', 'config_changed']\n\n        for m in methods:\n            setattr(Switcher, 'on_%s' % m, partial(self.trigger, m))\n\n        logging.debug(\"[switcher] triggers are ready to fire...\")\n"
  },
  {
    "path": "pwnagotchi/plugins/default/ups_lite.py",
    "content": "# Based on UPS Lite v1.1 from https://github.com/xenDE\n#\n# functions for get UPS status - needs enable \"i2c\" in raspi-config\n#\n# https://github.com/linshuqin329/UPS-Lite\n#\n# For Raspberry Pi Zero Ups Power Expansion Board with Integrated Serial Port S3U4\n# https://www.ebay.de/itm/For-Raspberry-Pi-Zero-Ups-Power-Expansion-Board-with-Integrated-Serial-Port-S3U4/323873804310\n# https://www.aliexpress.com/item/32888533624.html\n#\n# To display external power supply status you need to bridge the necessary pins on the UPS-Lite board. See instructions in the UPS-Lite repo.\nimport logging\nimport struct\n\nimport RPi.GPIO as GPIO\n\nimport pwnagotchi\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.components import LabeledValue\nfrom pwnagotchi.ui.view import BLACK\n\n\n# TODO: add enable switch in config.yml an cleanup all to the best place\nclass UPS:\n    def __init__(self):\n        # only import when the module is loaded and enabled\n        import smbus\n        # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)\n        self._bus = smbus.SMBus(1)\n\n    def voltage(self):\n        try:\n            address = 0x36\n            read = self._bus.read_word_data(address, 2)\n            swapped = struct.unpack(\"<H\", struct.pack(\">H\", read))[0]\n            return swapped * 1.25 / 1000 / 16\n        except:\n            return 0.0\n\n    def capacity(self):\n        try:\n            address = 0x36\n            read = self._bus.read_word_data(address, 4)\n            swapped = struct.unpack(\"<H\", struct.pack(\">H\", read))[0]\n            return swapped / 256\n        except:\n            return 0.0\n\n    def charging(self):\n        try:\n            GPIO.setmode(GPIO.BCM)\n            GPIO.setup(4, GPIO.IN)\n            return '+' if GPIO.input(4) == GPIO.HIGH else '-'\n        except:\n            return '-'\n\n\nclass UPSLite(plugins.Plugin):\n    __author__ = 'evilsocket@gmail.com'\n    __version__ = '1.0.0'\n    __license__ = 'GPL3'\n    __description__ = 'A plugin that will add a voltage indicator for the UPS Lite v1.1'\n\n    def __init__(self):\n        self.ups = None\n\n    def on_loaded(self):\n        self.ups = UPS()\n\n    def on_ui_setup(self, ui):\n        ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 + 15, 0),\n                                           label_font=fonts.Bold, text_font=fonts.Medium))\n\n    def on_unload(self, ui):\n        with ui._lock:\n            ui.remove_element('ups')\n\n    def on_ui_update(self, ui):\n        capacity = self.ups.capacity()\n        charging = self.ups.charging()\n        ui.set('ups', \"%2i%s\" % (capacity, charging))\n        if capacity <= self.options['shutdown']:\n            logging.info('[ups_lite] Empty battery (<= %s%%): shuting down' % self.options['shutdown'])\n            ui.update(force=True, new_data={'status': 'Battery exhausted, bye ...'})\n            pwnagotchi.shutdown()\n"
  },
  {
    "path": "pwnagotchi/plugins/default/watchdog.py",
    "content": "import os\nimport logging\nimport re\nimport subprocess\nfrom io import TextIOWrapper\nfrom pwnagotchi import plugins\n\n\nclass Watchdog(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '0.1.0'\n    __license__ = 'GPL3'\n    __description__ = 'Restart pwnagotchi when blindbug is detected.'\n\n    def __init__(self):\n        self.options = dict()\n        self.pattern = re.compile(r'brcmf_cfg80211_nexmon_set_channel.*?Set Channel failed')\n\n    def on_loaded(self):\n        \"\"\"\n        Gets called when the plugin gets loaded\n        \"\"\"\n        logging.info(\"Watchdog plugin loaded.\")\n\n    def on_epoch(self, agent, epoch, epoch_data):\n        # get last 10 lines\n        last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl','-n10','-k', '--since', '-5m'],\n                                                stdout=subprocess.PIPE).stdout))[-10:])\n        if len(self.pattern.findall(last_lines)) >= 5:\n            display = agent.view()\n            display.set('status', 'Blind-Bug detected. Restarting.')\n            display.update(force=True)\n            logging.info('[WATCHDOG] Blind-Bug detected. Restarting.')\n            mode = 'MANU' if agent.mode == 'manual' else 'AUTO'\n            import pwnagotchi\n            pwnagotchi.reboot(mode=mode)\n"
  },
  {
    "path": "pwnagotchi/plugins/default/webcfg.py",
    "content": "import logging\nimport json\nimport toml\nimport _thread\nfrom pwnagotchi import restart, plugins\nfrom pwnagotchi.utils import save_config\nfrom flask import abort\nfrom flask import render_template_string\n\nINDEX = \"\"\"\n{% extends \"base.html\" %}\n{% set active_page = \"plugins\" %}\n{% block title %}\n    Webcfg\n{% endblock %}\n\n{% block meta %}\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=0\" />\n{% endblock %}\n\n{% block styles %}\n{{ super() }}\n<style>\n    #divTop {\n        position: -webkit-sticky;\n        position: sticky;\n        top: 0px;\n        width: 100%;\n        font-size: 16px;\n        padding: 5px;\n        border: 1px solid #ddd;\n        margin-bottom: 5px;\n    }\n\n    #searchText {\n        width: 100%;\n    }\n\n    table {\n        table-layout: auto;\n        width: 100%;\n    }\n\n    table, th, td {\n      border: 1px solid black;\n      border-collapse: collapse;\n    }\n\n    th, td {\n      padding: 15px;\n      text-align: left;\n    }\n\n    table tr:nth-child(even) {\n      background-color: #eee;\n    }\n\n    table tr:nth-child(odd) {\n     background-color: #fff;\n    }\n\n    table th {\n      background-color: black;\n      color: white;\n    }\n\n    .remove {\n        background-color: #f44336;\n        color: white;\n        border: 2px solid #f44336;\n        padding: 4px 8px;\n        text-align: center;\n        text-decoration: none;\n        display: inline-block;\n        font-size: 12px;\n        margin: 4px 2px;\n        -webkit-transition-duration: 0.4s; /* Safari */\n        transition-duration: 0.4s;\n        cursor: pointer;\n    }\n\n    .remove:hover {\n        background-color: white;\n        color: black;\n    }\n\n    #btnSave {\n        position: -webkit-sticky;\n        position: sticky;\n        bottom: 0px;\n        width: 100%;\n        background-color: #0061b0;\n        border: none;\n        color: white;\n        padding: 15px 32px;\n        text-align: center;\n        text-decoration: none;\n        display: inline-block;\n        font-size: 16px;\n        cursor: pointer;\n        float: right;\n    }\n\n    #divTop {\n        display: table;\n        width: 100%;\n    }\n    #divTop > * {\n        display: table-cell;\n    }\n    #divTop > span {\n        width: 1%;\n    }\n    #divTop > input {\n        width: 100%;\n    }\n\n    @media screen and (max-width:700px) {\n        table, tr, td {\n            padding:0;\n            border:1px solid black;\n        }\n\n        table {\n            border:none;\n        }\n\n        tr:first-child, thead, th {\n            display:none;\n            border:none;\n        }\n\n        tr {\n            float: left;\n            width: 100%;\n            margin-bottom: 2em;\n        }\n\n        table tr:nth-child(odd) {\n            background-color: #eee;\n        }\n\n        td {\n            float: left;\n            width: 100%;\n            padding:1em;\n        }\n\n        td::before {\n            content:attr(data-label);\n            word-wrap: break-word;\n            background: #eee;\n            border-right:2px solid black;\n            width: 20%;\n            float:left;\n            padding:1em;\n            font-weight: bold;\n            margin:-1em 1em -1em -1em;\n        }\n\n        .del_btn_wrapper {\n            content:attr(data-label);\n            word-wrap: break-word;\n            background: #eee;\n            border-right:2px solid black;\n            width: 20%;\n            float:left;\n            padding:1em;\n            font-weight: bold;\n            margin:-1em 1em -1em -1em;\n        }\n    }\n</style>\n{% endblock %}\n\n{% block content %}\n    <div id=\"divTop\">\n        <input type=\"text\" id=\"searchText\" placeholder=\"Search for options ...\" title=\"Type an option name\">\n        <span><select id=\"selAddType\"><option value=\"text\">Text</option><option value=\"number\">Number</option></select></span>\n        <span><button id=\"btnAdd\" type=\"button\" onclick=\"addOption()\">+</button></span>\n    </div>\n    <button id=\"btnSave\" type=\"button\" onclick=\"saveConfig()\">Save and restart</button>\n    <div id=\"content\"></div>\n{% endblock %}\n\n{% block script %}\n        function addOption() {\n          var input, table, tr, td, divDelBtn, btnDel, selType, selTypeVal;\n          input = document.getElementById(\"searchText\");\n          inputVal = input.value;\n          selType = document.getElementById(\"selAddType\");\n          selTypeVal = selType.options[selType.selectedIndex].value;\n          table = document.getElementById(\"tableOptions\");\n          if (table) {\n            tr = table.insertRow();\n            // del button\n            divDelBtn = document.createElement(\"div\");\n            divDelBtn.className = \"del_btn_wrapper\";\n            td = document.createElement(\"td\");\n            td.setAttribute(\"data-label\", \"\");\n            btnDel = document.createElement(\"Button\");\n            btnDel.innerHTML = \"X\";\n            btnDel.onclick = function(){ delRow(this);};\n            btnDel.className = \"remove\";\n            divDelBtn.appendChild(btnDel);\n            td.appendChild(divDelBtn);\n            tr.appendChild(td);\n            // option\n            td = document.createElement(\"td\");\n            td.setAttribute(\"data-label\", \"Option\");\n            td.innerHTML = inputVal;\n            tr.appendChild(td);\n            // value\n            td = document.createElement(\"td\");\n            td.setAttribute(\"data-label\", \"Value\");\n            input = document.createElement(\"input\");\n            input.type = selTypeVal;\n            input.value = \"\";\n            td.appendChild(input);\n            tr.appendChild(td);\n\n            input.value = \"\";\n          }\n        }\n\n        function saveConfig(){\n            // get table\n            var table = document.getElementById(\"tableOptions\");\n            if (table) {\n                var json = tableToJson(table);\n                sendJSON(\"webcfg/save-config\", json, function(response) {\n                    if (response) {\n                        if (response.status == \"200\") {\n                            alert(\"Config got updated\");\n                        } else {\n                            alert(\"Error while updating the config (err-code: \" + response.status + \")\");\n                        }\n                    }\n                });\n            }\n        }\n        var searchInput = document.getElementById(\"searchText\");\n        searchInput.onkeyup = function() {\n            var filter, table, tr, td, i, txtValue;\n            filter = searchInput.value.toUpperCase();\n            table = document.getElementById(\"tableOptions\");\n            if (table) {\n                tr = table.getElementsByTagName(\"tr\");\n\n                for (i = 0; i < tr.length; i++) {\n                    td = tr[i].getElementsByTagName(\"td\")[1];\n                    if (td) {\n                        txtValue = td.textContent || td.innerText;\n                        if (txtValue.toUpperCase().indexOf(filter) > -1) {\n                            tr[i].style.display = \"\";\n                        }else{\n                            tr[i].style.display = \"none\";\n                        }\n                    }\n                }\n            }\n        }\n\n        function sendJSON(url, data, callback) {\n          var xobj = new XMLHttpRequest();\n          var csrf = \"{{ csrf_token() }}\";\n          xobj.open('POST', url);\n          xobj.setRequestHeader(\"Content-Type\", \"application/json\");\n          xobj.setRequestHeader('x-csrf-token', csrf);\n          xobj.onreadystatechange = function () {\n                if (xobj.readyState == 4) {\n                  callback(xobj);\n                }\n          };\n          xobj.send(JSON.stringify(data));\n        }\n\n        function loadJSON(url, callback) {\n          var xobj = new XMLHttpRequest();\n          xobj.overrideMimeType(\"application/json\");\n          xobj.open('GET', url, true);\n          xobj.onreadystatechange = function () {\n                if (xobj.readyState == 4 && xobj.status == \"200\") {\n                  callback(JSON.parse(xobj.responseText));\n                }\n          };\n          xobj.send(null);\n        }\n\n        // https://stackoverflow.com/questions/19098797/fastest-way-to-flatten-un-flatten-nested-json-objects\n        function unFlattenJson(data) {\n            \"use strict\";\n            if (Object(data) !== data || Array.isArray(data))\n                return data;\n            var result = {}, cur, prop, idx, last, temp, inarray;\n            for(var p in data) {\n                cur = result, prop = \"\", last = 0, inarray = false;\n                do {\n                    idx = p.indexOf(\".\", last);\n                    temp = p.substring(last, idx !== -1 ? idx : undefined);\n                    inarray = temp.startsWith('#') && !isNaN(parseInt(temp.substring(1)))\n                    cur = cur[prop] || (cur[prop] = (inarray ? [] : {}));\n                    if (inarray){\n                        prop = temp.substring(1);\n                    }else{\n                        prop = temp;\n                    }\n                    last = idx + 1;\n                } while(idx >= 0);\n                cur[prop] = data[p];\n            }\n            return result[\"\"];\n        }\n\n        function flattenJson(data) {\n            var result = {};\n            function recurse (cur, prop) {\n                if (Object(cur) !== cur) {\n                    result[prop] = cur;\n                } else if (Array.isArray(cur)) {\n                     for(var i=0, l=cur.length; i<l; i++)\n                         recurse(cur[i], prop ? prop+\".#\"+i : \"\"+i);\n                    if (l == 0)\n                        result[prop] = [];\n                } else {\n                    var isEmpty = true;\n                    for (var p in cur) {\n                        isEmpty = false;\n                        recurse(cur[p], prop ? prop+\".\"+p : p);\n                    }\n                    if (isEmpty)\n                        result[prop] = {};\n                }\n            }\n            recurse(data, \"\");\n            return result;\n        }\n\n        function delRow(btn) {\n            var tr = btn.parentNode.parentNode.parentNode;\n            tr.parentNode.removeChild(tr);\n        }\n\n        function jsonToTable(json) {\n            var table = document.createElement(\"table\");\n            table.id = \"tableOptions\";\n\n            // create header\n            var tr = table.insertRow();\n            var thDel = document.createElement(\"th\");\n            thDel.innerHTML = \"\";\n            var thOpt = document.createElement(\"th\");\n            thOpt.innerHTML = \"Option\";\n            var thVal = document.createElement(\"th\");\n            thVal.innerHTML = \"Value\";\n            tr.appendChild(thDel);\n            tr.appendChild(thOpt);\n            tr.appendChild(thVal);\n\n            var td, divDelBtn, btnDel;\n            // iterate over keys\n            Object.keys(json).forEach(function(key) {\n                tr = table.insertRow();\n                // del button\n                divDelBtn = document.createElement(\"div\");\n                divDelBtn.className = \"del_btn_wrapper\";\n                td = document.createElement(\"td\");\n                td.setAttribute(\"data-label\", \"\");\n                btnDel = document.createElement(\"Button\");\n                btnDel.innerHTML = \"X\";\n                btnDel.onclick = function(){ delRow(this);};\n                btnDel.className = \"remove\";\n                divDelBtn.appendChild(btnDel);\n                td.appendChild(divDelBtn);\n                tr.appendChild(td);\n                // option\n                td = document.createElement(\"td\");\n                td.setAttribute(\"data-label\", \"Option\");\n                td.innerHTML = key;\n                tr.appendChild(td);\n                // value\n                td = document.createElement(\"td\");\n                td.setAttribute(\"data-label\", \"Value\");\n                if(typeof(json[key])==='boolean'){\n                    input = document.createElement(\"select\");\n                    input.setAttribute(\"id\", \"boolSelect\");\n                    tvalue = document.createElement(\"option\");\n                    tvalue.setAttribute(\"value\", \"true\");\n                    ttext = document.createTextNode(\"True\")\n                    tvalue.appendChild(ttext);\n                    fvalue = document.createElement(\"option\");\n                    fvalue.setAttribute(\"value\", \"false\");\n                    ftext = document.createTextNode(\"False\");\n                    fvalue.appendChild(ftext);\n                    input.appendChild(tvalue);\n                    input.appendChild(fvalue);\n                    input.value = json[key];\n                    document.body.appendChild(input);\n                    td.appendChild(input);\n                    tr.appendChild(td);\n                } else {\n                    input = document.createElement(\"input\");\n                    if(Array.isArray(json[key])) {\n                        input.type = 'text';\n                        input.value = '[]';\n                    }else{\n                        input.type = typeof(json[key]);\n                        input.value = json[key];\n                    }\n                    td.appendChild(input);\n                    tr.appendChild(td);\n                }\n            });\n\n            return table;\n        }\n\n        function tableToJson(table) {\n            var rows = table.getElementsByTagName(\"tr\");\n            var i, td, key, value;\n            var json = {};\n\n            for (i = 0; i < rows.length; i++) {\n                td = rows[i].getElementsByTagName(\"td\");\n                if (td.length == 3) {\n                    // td[0] = del button\n                    key = td[1].textContent || td[1].innerText;\n                    var input = td[2].getElementsByTagName(\"input\");\n                    var select = td[2].getElementsByTagName(\"select\");\n                    if (input && input != undefined && input.length > 0 ) {\n                        if (input[0].type == \"text\") {\n                            if (input[0].value.startsWith(\"[\") && input[0].value.endsWith(\"]\")) {\n                                json[key] = JSON.parse(input[0].value);\n                            }else{\n                                json[key] = input[0].value;\n                            }\n                        }else if (input[0].type == \"number\") {\n                            json[key] = Number(input[0].value);\n                        }\n                    } else if(select && select != undefined && select.length > 0) {\n                        var myValue = select[0].options[select[0].selectedIndex].value;\n                        json[key] = myValue === 'true';\n                    }\n                }\n            }\n            return unFlattenJson(json);\n        }\n\n        loadJSON(\"webcfg/get-config\", function(response) {\n            var flat_json = flattenJson(response);\n            var table = jsonToTable(flat_json);\n            var divContent = document.getElementById(\"content\");\n            divContent.innerHTML = \"\";\n            divContent.appendChild(table);\n        });\n{% endblock %}\n\"\"\"\n\ndef serializer(obj):\n    if isinstance(obj, set):\n        return list(obj)\n    raise TypeError\n\nclass WebConfig(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '1.0.0'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin allows the user to make runtime changes.'\n\n    def __init__(self):\n        self.ready = False\n        self.mode = 'MANU'\n\n    def on_config_changed(self, config):\n        self.config = config\n        self.ready = True\n\n    def on_ready(self, agent):\n        self.mode = 'MANU' if agent.mode == 'manual' else 'AUTO'\n\n    def on_internet_available(self, agent):\n        self.mode = 'MANU' if agent.mode == 'manual' else 'AUTO'\n\n    def on_loaded(self):\n        \"\"\"\n        Gets called when the plugin gets loaded\n        \"\"\"\n        logging.info(\"webcfg: Plugin loaded.\")\n\n\n    def on_webhook(self, path, request):\n        \"\"\"\n        Serves the current configuration\n        \"\"\"\n        if not self.ready:\n            return \"Plugin not ready\"\n\n        if request.method == \"GET\":\n            if path == \"/\" or not path:\n                return render_template_string(INDEX)\n            elif path == \"get-config\":\n                # send configuration\n                return json.dumps(self.config, default=serializer)\n            else:\n                abort(404)\n        elif request.method == \"POST\":\n            if path == \"save-config\":\n                try:\n                    save_config(request.get_json(), '/etc/pwnagotchi/config.toml') # test\n                    _thread.start_new_thread(restart, (self.mode,))\n                    return \"success\"\n                except Exception as ex:\n                    logging.error(ex)\n                    return \"config error\", 500\n        abort(404)\n"
  },
  {
    "path": "pwnagotchi/plugins/default/webgpsmap.html",
    "content": "<html>\n<head>\n  <meta http-equiv=\"Content-Type\" content=\"text/xml; charset=utf-8\" />\n  <title>GPS MAP</title>\n  <link rel=\"stylesheet\" href=\"https://unpkg.com/leaflet@1.5.1/dist/leaflet.css\"/>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.4.1/MarkerCluster.css\" />\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.4.1/MarkerCluster.Default.css\" />\n  <script type='text/javascript' src=\"https://unpkg.com/leaflet@1.5.1/dist/leaflet.js\"></script>\n  <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.4.1/leaflet.markercluster.js'></script>\n  <style type=\"text/css\">\n    /* for map */\n    html, body {   height: 100%; width: 100%; margin:0; background-color:#000;}\n    .pwnAPPin path {\n      fill: #ce7575;\n    }\n    .pwnAPPinOpen path {\n      fill: #76ce75;\n    }\n    /* animated ap marker */\n    .pwnAPPin .ring_outer, .pwnAPPinOpen .ring_outer {\n      animation: opacityPulse 2s cubic-bezier(1, 0.14, 1, 1);\n      animation-iteration-count: infinite;\n      opacity: .5;\n    }\n    .pwnAPPin .ring_inner, .pwnAPPinOpen .ring_inner {\n      animation: opacityPulse 2s cubic-bezier(0.4, 0.74, 0.56, 0.82);\n      animation-iteration-count: infinite;\n      opacity: .8;\n    }\n    @keyframes opacityPulse {\n      0% {\n        opacity: 0.1;\n      }\n      50% {\n        opacity: 1.0;\n      }\n      100% {\n        opacity: 0.1;\n      }\n    }\n    @keyframes bounceInDown {\n      from, 60%, 75%, 90%, to {\n        animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);\n      }\n      0% {\n        opacity: 0;\n        transform: translate3d(0, -3000px, 0);\n      }\n      60% {\n        opacity: 1;\n        transform: translate3d(0, 5px, 0);\n      }\n      75% {\n        transform: translate3d(0, -3px, 0);\n      }\n      90% {\n        transform: translate3d(0, 5px, 0);\n      }\n      to {\n        transform: none;\n      }\n    }\n    .bounceInDown {\n      animation-name: bounceInDown;\n      animation-duration: 2s;\n      animation-fill-mode: both;\n    }\n    /* animated radar */\n    .radar {\n    animation: pulsate 1s ease-out;\n    -webkit-animation: pulsate 1s ease-out;\n    -webkit-animation-iteration-count: infinite;\n    /* opacity: 0.0 */\n    }\n    #loading {\n      top: 50%;\n      left: 50%;\n      position: fixed;\n      background-color: rgba(255, 255, 255, 0.9);\n      border: 0.5vw #ff0000 solid;\n      border-radius: 2vw;\n      padding: 5vw;\n      transform: translateX(-50%) translateY(-50%);\n      text-align:center;\n      display: none;\n    }\n    #loading .face { font-size:8vw; }\n    #loading .text { position:absolute;bottom:0;text-align:center; font-size: 2vw;color:#a0a0a0;}\n    #filterbox { position: fixed;top:0px;left:0px;z-index:999999;margin-left:55px;width:100%;height:20px;border-bottom:2px solid #303030;display: grid;grid-template-columns: 1fr 0.1fr;grid-template-rows: 1fr;grid-template-areas: \". .\";}\n      #search { grid-area: 1 / 1 / 2 / 2;height:30px;padding:3px;background-color:#000;color:#e0e0e0;border:none;}\n      #matchcount { grid-area: 1 / 2 / 2 / 3;height:30px;margin-right:55px;padding-right:5px;background-color:#000;color:#a0a0a0;font-weight:bold;}\n      #mapdiv { width:100%; height: 100%; }\n  </style>\n</head>\n<body>\n  <div id=\"mapdiv\"></div>\n  <div id=\"filterbox\">\n    <input type=\"text\" id=\"search\" placeholder=\"filter: #cracked #notcracked AA:BB:CC aabbcc AndroidAP ...\"/>\n    <div id=\"matchcount\">0&nbsp;APs</div>\n  </div>\n  <div id=\"loading\"><div class=\"face\"><nobr>(⌐■&nbsp;<span id=\"loading_ap_img\"></span>&nbsp;■)</nobr></div><div class=\"text\" id=\"loading_infotext\">loading positions...</div></div>\n  <script type=\"text/javascript\">\n    function loadJSON(url, callback) {\n      document.getElementById(\"loading\").style.display = \"flex\";\n      var xobj = new XMLHttpRequest();\n      xobj.overrideMimeType(\"application/json\");\n      xobj.open('GET', url, true);\n      xobj.onreadystatechange = function () {\n        if (xobj.readyState == 4 && xobj.status == \"200\") {\n          callback(xobj.responseText);\n        }\n      };\n      xobj.send(null);\n    }\n    function escapeHtml(unsafe) {\n      return String(unsafe)\n          .replace(/&/g, \"&amp;\")\n          .replace(/</g, \"&lt;\")\n          .replace(/>/g, \"&gt;\")\n          .replace(/\"/g, \"&quot;\")\n          .replace(/'/g, \"&#039;\");\n    }\n    function formatMacAddress(macAddress) {\n      if (macAddress !== null) {\n        macAddress = macAddress.toUpperCase();\n        if (macAddress.length >= 3 && macAddress.length <= 16) {\n          macAddress = macAddress.replace(/\\W/ig, '');\n          macAddress = macAddress.replace(/(.{2})/g, \"$1:\");\n          macAddress = macAddress.replace(/:+$/,'');\n        }\n      }\n      return macAddress;\n    }\n\n    // select your map theme from https://leaflet-extras.github.io/leaflet-providers/preview/\n    // use 2 layers with alpha for a nice dark style\n    var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {\n        attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'\n    });\n    var CartoDB_DarkMatter = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {\n      attribution: '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors &copy; <a href=\"https://carto.com/attributions\">CARTO</a>',\n      subdomains: 'abcd',\n      opacity:0.8,\n      maxZoom: 20\n    });\n    var mymap = L.map('mapdiv');\n\n    var svg     = '<svg class=\"pwnAPPin\" width=\"80px\" height=\"60px\" viewBox=\"0 0 44 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><desc>pwnagotchi AP icon.</desc><defs><linearGradient x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\" id=\"linearGradient-1\"><stop stop-color=\"#FFFFFF\" offset=\"0%\"></stop><stop stop-color=\"#000000\" offset=\"100%\"></stop></linearGradient></defs><g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\"><g id=\"marker\"><path class=\"ring_outer\" d=\"M28.6,8 C34.7,9.4 39,12.4 39,16 C39,20.7 31.3,24.6 21.7,24.6 C12.1,24.6 4.3,20.7 4.3,16 C4.3,12.5 8.5,9.5 14.6,8.1 C15.3,8 14.2,6.6 13.3,6.8 C5.5,8.4 0,12.2 0,16.7 C0,22.7 9.7,27.4 21.7,27.4 C33.7,27.4 43.3,22.6 43.3,16.7 C43.3,12.1 37.6,8.3 29.6,6.7 C28.8,6.5 27.8,7.9 28.6,8.1 L28.6,8 Z\" id=\"Shape\" fill=\"#878787\" fill-rule=\"nonzero\"></path><path class=\"ring_inner\" d=\"M28.1427313,11.0811939 C30.4951542,11.9119726 32.0242291,13.2174821 32.0242291,14.6416742 C32.0242291,17.2526931 27.6722467,19.2702986 22.261674,19.2702986 C16.8511013,19.2702986 12.4991189,17.2526931 12.4991189,14.7603569 C12.4991189,13.5735301 13.4400881,12.505386 15.0867841,11.6746073 C15.792511,11.3185592 14.7339207,9.30095371 13.9105727,9.77568442 C10.6171806,10.9625112 8.5,12.9801167 8.5,15.2350876 C8.5,19.0329333 14.4986784,22.0000002 21.9088106,22.0000002 C29.2013216,22.0000002 35.2,19.0329333 35.2,15.2350876 C35.2,12.861434 32.7299559,10.6064632 28.8484581,9.30095371 C28.0251101,9.18227103 27.4370044,10.8438285 28.0251101,11.0811939 L28.1427313,11.0811939 Z\" id=\"Shape\" fill=\"#5F5F5F\" fill-rule=\"nonzero\"></path><g id=\"ap\" transform=\"translate(13.000000, 0.000000)\"><rect id=\"apfront\" fill=\"#000000\" x=\"0\" y=\"14\" width=\"18\" height=\"4\"></rect><polygon id=\"apbody\" fill=\"url(#linearGradient-1)\" points=\"3.83034404 10 14.169656 10 18 14 0 14\"></polygon><circle class=\"ring_outer\" id=\"led1\" fill=\"#931F1F\" cx=\"3\" cy=\"16\" r=\"1\"></circle><circle class=\"ring_inner\" id=\"led2\" fill=\"#931F1F\" cx=\"7\" cy=\"16\" r=\"1\"></circle><circle class=\"ring_outer\" id=\"led3\" fill=\"#931F1F\" cx=\"11\" cy=\"16\" r=\"1\"></circle><circle class=\"ring_inner\" id=\"led4\" fill=\"#931F1F\" cx=\"15\" cy=\"16\" r=\"1\"></circle><polygon id=\"antenna2\" fill=\"#000000\" points=\"8.8173082 0 9.1826918 0 9.5 11 8.5 11\"></polygon><polygon id=\"antenna3\" fill=\"#000000\" transform=\"translate(15.000000, 5.500000) rotate(15.000000) translate(-15.000000, -5.500000) \" points=\"14.8173082 0 15.1826918 0 15.5 11 14.5 11\"></polygon><polygon id=\"antenna1\" fill=\"#000000\" transform=\"translate(3.000000, 5.500000) rotate(-15.000000) translate(-3.000000, -5.500000) \" points=\"2.8173082 0 3.1826918 0 3.5 11 2.5 11\"></polygon></g></g></g></svg>';\n    var svgOpen = '<svg class=\"pwnAPPinOpen\" width=\"80px\" height=\"60px\" viewBox=\"0 0 44 28\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><desc>pwnagotchi AP icon.</desc><defs><linearGradient x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"100%\" id=\"linearGradient-1\"><stop stop-color=\"#FFFFFF\" offset=\"0%\"></stop><stop stop-color=\"#000000\" offset=\"100%\"></stop></linearGradient></defs><g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\"><g id=\"marker\"><path class=\"ring_outer\" d=\"M28.6,8 C34.7,9.4 39,12.4 39,16 C39,20.7 31.3,24.6 21.7,24.6 C12.1,24.6 4.3,20.7 4.3,16 C4.3,12.5 8.5,9.5 14.6,8.1 C15.3,8 14.2,6.6 13.3,6.8 C5.5,8.4 0,12.2 0,16.7 C0,22.7 9.7,27.4 21.7,27.4 C33.7,27.4 43.3,22.6 43.3,16.7 C43.3,12.1 37.6,8.3 29.6,6.7 C28.8,6.5 27.8,7.9 28.6,8.1 L28.6,8 Z\" id=\"Shape\" fill=\"#878787\" fill-rule=\"nonzero\"></path><path class=\"ring_inner\" d=\"M28.1427313,11.0811939 C30.4951542,11.9119726 32.0242291,13.2174821 32.0242291,14.6416742 C32.0242291,17.2526931 27.6722467,19.2702986 22.261674,19.2702986 C16.8511013,19.2702986 12.4991189,17.2526931 12.4991189,14.7603569 C12.4991189,13.5735301 13.4400881,12.505386 15.0867841,11.6746073 C15.792511,11.3185592 14.7339207,9.30095371 13.9105727,9.77568442 C10.6171806,10.9625112 8.5,12.9801167 8.5,15.2350876 C8.5,19.0329333 14.4986784,22.0000002 21.9088106,22.0000002 C29.2013216,22.0000002 35.2,19.0329333 35.2,15.2350876 C35.2,12.861434 32.7299559,10.6064632 28.8484581,9.30095371 C28.0251101,9.18227103 27.4370044,10.8438285 28.0251101,11.0811939 L28.1427313,11.0811939 Z\" id=\"Shape\" fill=\"#5F5F5F\" fill-rule=\"nonzero\"></path><g id=\"ap\" transform=\"translate(13.000000, 0.000000)\"><rect id=\"apfront\" fill=\"#000000\" x=\"0\" y=\"14\" width=\"18\" height=\"4\"></rect><polygon id=\"apbody\" fill=\"url(#linearGradient-1)\" points=\"3.83034404 10 14.169656 10 18 14 0 14\"></polygon><circle class=\"ring_outer\" id=\"led1\" fill=\"#1f9321\" cx=\"3\" cy=\"16\" r=\"1\"></circle><circle class=\"ring_inner\" id=\"led2\" fill=\"#1f9321\" cx=\"7\" cy=\"16\" r=\"1\"></circle><circle class=\"ring_outer\" id=\"led3\" fill=\"#1f9321\" cx=\"11\" cy=\"16\" r=\"1\"></circle><circle class=\"ring_inner\" id=\"led4\" fill=\"#1f9321\" cx=\"15\" cy=\"16\" r=\"1\"></circle><polygon id=\"antenna2\" fill=\"#000000\" points=\"8.8173082 0 9.1826918 0 9.5 11 8.5 11\"></polygon><polygon id=\"antenna3\" fill=\"#000000\" transform=\"translate(15.000000, 5.500000) rotate(15.000000) translate(-15.000000, -5.500000) \" points=\"14.8173082 0 15.1826918 0 15.5 11 14.5 11\"></polygon><polygon id=\"antenna1\" fill=\"#000000\" transform=\"translate(3.000000, 5.500000) rotate(-15.000000) translate(-3.000000, -5.500000) \" points=\"2.8173082 0 3.1826918 0 3.5 11 2.5 11\"></polygon></g></g></g></svg>';\n    document.getElementById('loading_ap_img').innerHTML = svg;\n    var myIcon = L.divIcon({\n      className: \"leaflet-data-marker\",\n      html: svg.replace('#','%23'),\n      iconAnchor  : [40, 30],\n      iconSize    : [80, 60],\n      popupAnchor : [0, -30],\n    });\n    var myIconOpen = L.divIcon({\n      className: \"leaflet-data-marker\",\n      html: svgOpen.replace('#','%23'),\n      iconAnchor  : [40, 30],\n      iconSize    : [80, 60],\n      popupAnchor : [0, -30],\n    });\n\n    var positionsLoaded = false;\n    var positions = [];\n    var accuracys = [];\n    var markers = [];\n    var marker_pos = [];\n    var markerClusters = L.markerClusterGroup();\n\n    function drawPositions() {\n      count = 0;\n      //mymap.removeLayer(markerClusters);\n      mymap.eachLayer(function (layer) {\n        mymap.removeLayer(layer);\n      });\n      Esri_WorldImagery.addTo(mymap);\n      CartoDB_DarkMatter.addTo(mymap);\n      markerClusters = L.markerClusterGroup();\n      accuracys = [];\n      markers = [];\n      marker_pos = [];\n      filterText = document.getElementById(\"search\").value;\n      //console.log(filterText);\n      Object.keys(positions).forEach(function(key) {\n        if(positions[key].lng){\n          filterPattern =\n            positions[key].ssid + ' ' +\n            formatMacAddress(positions[key].mac) + ' ' +\n            positions[key].mac\n          ;\n          if (positions[key].pass) {\n            filterPattern += positions[key].pass + ' #cracked';\n          } else {\n            filterPattern += ' #notcracked';\n          }\n          filterPattern = filterPattern.toLowerCase();\n          //console.log(filterPattern);\n          var matched = true;\n          if (filterText) {\n              filterText.split(\" \").forEach(function (item) {\n                if (!filterPattern.includes(item.toLowerCase())) {\n                  matched = false;\n                }\n              });\n          }\n          if (matched) {\n            count++;\n            new_marker_pos = [positions[key].lat, positions[key].lng];\n            if (positions[key].acc) {\n              radius = Math.round(Math.min(positions[key].acc, 500));\n              markerColor = 'red';\n              markerColorCode = '#f03';\n              fillOpacity = 0.002;\n              if (positions[key].pass) {\n                markerColor = 'green';\n                markerColorCode = '#1aff00';\n                fillOpacity = 0.1;\n              }\n              accuracys.push(\n                L.circle(new_marker_pos, {\n                  color: markerColor,\n                  fillColor: markerColorCode,\n                  fillOpacity: fillOpacity,\n                  weight: 1,\n                  opacity: 0.1,\n                  radius: Math.min(positions[key].acc, 500),\n                }).setStyle({'className': 'radar'}).addTo(mymap)\n              );\n            }\n            passInfo = '';\n            if (positions[key].pass) {\n              passInfo = '<br/><b>Pass:</b> '+escapeHtml(positions[key].pass);\n              newMarker = L.marker(new_marker_pos, { icon: myIconOpen, title: positions[key].ssid }); //.addTo(mymap);\n            } else {\n              newMarker = L.marker(new_marker_pos, { icon: myIcon, title: positions[key].ssid }); //.addTo(mymap);\n            }\n            newMarker.bindPopup(\"<b>\"+escapeHtml(positions[key].ssid)+\"</b><br><nobr>MAC: \"+escapeHtml(formatMacAddress(positions[key].mac))+\"</nobr><br/>\"+\"<nobr>position type: \"+escapeHtml(positions[key].type)+\"</nobr><br/>\"+\"<nobr>position accuracy: \"+escapeHtml(Math.round(positions[key].acc))+\"</nobr>\"+passInfo, { maxWidth: \"auto\" });\n            markers.push(newMarker);\n            marker_pos.push(new_marker_pos);\n            markerClusters.addLayer( newMarker );\n          }\n        }\n      });\n      document.getElementById(\"matchcount\").innerHTML = count + \"&nbsp;APs\";\n      if (count > 0) {\n        mymap.addLayer( markerClusters );\n        var bounds = new L.LatLngBounds(marker_pos);\n        mymap.fitBounds(bounds);\n        document.getElementById(\"loading\").style.display = \"none\";\n      } else {\n        document.getElementById(\"loading_infotext\").innerHTML = \"NO POSITION DATA FOUND :(\";\n      }\n    }\n\n    // draw map on Enter in FilterInputField\n    const node = document.getElementById(\"search\").addEventListener(\"keyup\", function(event) {\n      if (event.key === \"Enter\") {\n        if (positionsLoaded) {\n          drawPositions();\n        }\n      }\n    });\n\n    // load positions\n    loadJSON(\"/plugins/webgpsmap/all\", function(response) {\n      positions = JSON.parse(response);\n      positionsLoaded = true;\n      drawPositions();\n    });\n    // get current position and set marker in interval if https request\n    if (location.protocol === 'https:') {\n      var myLocationMarker = {};\n      function onLocationFound(e) {\n        if (myLocationMarker != undefined) {\n          mymap.removeLayer(myLocationMarker);\n        };\n        myLocationMarker = L.marker(e.latlng).addTo(mymap);\n        setTimeout(function(){ mymap.locate(); }, 30000);\n      }\n      mymap.on('locationfound', onLocationFound);\n      mymap.locate({setView: true});\n    }\n  </script>\n</body></html>\n"
  },
  {
    "path": "pwnagotchi/plugins/default/webgpsmap.py",
    "content": "import pwnagotchi.plugins as plugins\nimport logging\nimport os\nimport json\nimport re\nimport datetime\nfrom flask import Response\nfrom functools import lru_cache\nfrom dateutil.parser import parse\n\n'''\n    webgpsmap shows existing position data stored in your /handshakes/ directory\n\n    the plugin does the following:\n        - search for *.pcap files in your /handshakes/ dir\n            - for every found .pcap file it looks for a .geo.json or .gps.json or .paw-gps.json file with\n              latitude+longitude data inside and shows this position on the map\n            - if also an .cracked file with a plaintext password inside exist, it reads the content and shows the\n              position as green instead of red and the password inside the infopox of the position\n    special:\n        you can save the html-map as one file for offline use or host on your own webspace with \"/plugins/webgpsmap/offlinemap\"\n\n'''\n\nclass Webgpsmap(plugins.Plugin):\n    __author__ = 'https://github.com/xenDE and https://github.com/dadav'\n    __version__ = '1.4.0'\n    __name__ = 'webgpsmap'\n    __license__ = 'GPL3'\n    __description__ = 'a plugin for pwnagotchi that shows a openstreetmap with positions of ap-handshakes in your webbrowser'\n\n    ALREADY_SENT = list()\n    SKIP = list()\n\n    def __init__(self):\n        self.ready = False\n\n    def on_config_changed(self, config):\n        self.config = config\n        self.ready = True\n\n    def on_loaded(self):\n        \"\"\"\n        Plugin got loaded\n        \"\"\"\n        logging.info(\"[webgpsmap]: plugin loaded\")\n\n    def on_webhook(self, path, request):\n        \"\"\"\n        Returns ewquested data\n        \"\"\"\n        # defaults:\n        response_header_contenttype = None\n        response_header_contentdisposition = None\n        response_mimetype = \"application/xhtml+xml\"\n        if not self.ready:\n            try:\n                response_data = bytes('''<html>\n                    <head>\n                    <meta charset=\"utf-8\"/>\n                    <style>body{font-size:1000%;}</style>\n                    </head>\n                    <body>Not ready yet</body>\n                    </html>''', \"utf-8\")\n                response_status = 500\n                response_mimetype = \"application/xhtml+xml\"\n                response_header_contenttype = 'text/html'\n            except Exception as error:\n                logging.error(f\"[webgpsmap] on_webhook NOT_READY error: {error}\")\n                return\n        else:\n            if request.method == \"GET\":\n                if path == '/' or not path:\n                    # returns the html template\n                    self.ALREADY_SENT = list()\n                    try:\n                        response_data = bytes(self.get_html(), \"utf-8\")\n                    except Exception as error:\n                        logging.error(f\"[webgpsmap] on_webhook / error: {error}\")\n                        return\n                    response_status = 200\n                    response_mimetype = \"application/xhtml+xml\"\n                    response_header_contenttype = 'text/html'\n                elif path.startswith('all'):\n                    # returns all positions\n                    try:\n                        self.ALREADY_SENT = list()\n                        response_data = bytes(json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])), \"utf-8\")\n                        response_status = 200\n                        response_mimetype = \"application/json\"\n                        response_header_contenttype = 'application/json'\n                    except Exception as error:\n                        logging.error(f\"[webgpsmap] on_webhook all error: {error}\")\n                        return\n                elif path.startswith('offlinemap'):\n                    # for download an all-in-one html file with positions.json inside\n                    try:\n                        self.ALREADY_SENT = list()\n                        json_data = json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes']))\n                        html_data = self.get_html()\n                        html_data = html_data.replace('var positions = [];', 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();')\n                        response_data = bytes(html_data, \"utf-8\")\n                        response_status = 200\n                        response_mimetype = \"application/xhtml+xml\"\n                        response_header_contenttype = 'text/html'\n                        response_header_contentdisposition = 'attachment; filename=webgpsmap.html';\n                    except Exception as error:\n                        logging.error(f\"[webgpsmap] on_webhook offlinemap: error: {error}\")\n                        return\n                # elif path.startswith('/newest'):\n                #     # returns all positions newer then timestamp\n                #     response_data = bytes(json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes']), newest_only=True), \"utf-8\")\n                #     response_status = 200\n                #     response_mimetype = \"application/json\"\n                #     response_header_contenttype = 'application/json'\n                else:\n                    # unknown GET path\n                    response_data = bytes('''<html>\n                    <head>\n                    <meta charset=\"utf-8\"/>\n                    <style>body{font-size:1000%;}</style>\n                    </head>\n                    <body>4😋4</body>\n                    </html>''', \"utf-8\")\n                    response_status = 404\n            else:\n                # unknown request.method\n                response_data = bytes('''<html>\n                    <head>\n                    <meta charset=\"utf-8\"/>\n                    <style>body{font-size:1000%;}</style>\n                    </head>\n                    <body>4😋4 for bad boys</body>\n                    </html>''', \"utf-8\")\n                response_status = 404\n        try:\n            r = Response(response=response_data, status=response_status, mimetype=response_mimetype)\n            if response_header_contenttype is not None:\n                r.headers[\"Content-Type\"] = response_header_contenttype\n            if response_header_contentdisposition is not None:\n                r.headers[\"Content-Disposition\"] = response_header_contentdisposition\n            return r\n        except Exception as error:\n            logging.error(f\"[webgpsmap] on_webhook CREATING_RESPONSE error: {error}\")\n            return\n\n    # cache 2048 items\n    @lru_cache(maxsize=2048, typed=False)\n    def _get_pos_from_file(self, path):\n        return PositionFile(path)\n\n\n    def load_gps_from_dir(self, gpsdir, newest_only=False):\n        \"\"\"\n        Parses the gps-data from disk\n        \"\"\"\n\n        handshake_dir = gpsdir\n        gps_data = dict()\n\n        logging.info(f\"[webgpsmap] scanning {handshake_dir}\")\n\n\n        all_files = os.listdir(handshake_dir)\n        #print(all_files)\n        all_pcap_files = [os.path.join(handshake_dir, filename)\n                                for filename in all_files\n                                if filename.endswith('.pcap')\n                                ]\n        all_geo_or_gps_files = []\n        for filename_pcap in all_pcap_files:\n            filename_base = filename_pcap[:-5]  # remove \".pcap\"\n            logging.debug(f\"[webgpsmap] found: {filename_base}\")\n            filename_position = None\n\n            logging.debug(\"[webgpsmap] search for .gps.json\")\n            check_for = os.path.basename(filename_base) + \".gps.json\"\n            if check_for in all_files:\n                filename_position = str(os.path.join(handshake_dir, check_for))\n\n            logging.debug(\"[webgpsmap] search for .geo.json\")\n            check_for = os.path.basename(filename_base) + \".geo.json\"\n            if check_for in all_files:\n                filename_position = str(os.path.join(handshake_dir, check_for))\n\n            logging.debug(\"[webgpsmap] search for .paw-gps.json\")\n            check_for = os.path.basename(filename_base) + \".paw-gps.json\"\n            if check_for in all_files:\n                filename_position = str(os.path.join(handshake_dir, check_for))\n\n            logging.debug(f\"[webgpsmap] end search for position data files and use {filename_position}\")\n\n            if filename_position is not None:\n                all_geo_or_gps_files.append(filename_position)\n\n    #    all_geo_or_gps_files = set(all_geo_or_gps_files) - set(SKIP)   # remove skipped networks? No!\n\n        if newest_only:\n            all_geo_or_gps_files = set(all_geo_or_gps_files) - set(self.ALREADY_SENT)\n\n        logging.info(f\"[webgpsmap] Found {len(all_geo_or_gps_files)} position-data files from {len(all_pcap_files)} handshakes. Fetching positions ...\")\n\n        for pos_file in all_geo_or_gps_files:\n            try:\n                pos = self._get_pos_from_file(pos_file)\n                if not pos.type() == PositionFile.GPS and not pos.type() == PositionFile.GEO and not pos.type() == PositionFile.PAWGPS:\n                    continue\n\n                ssid, mac = pos.ssid(), pos.mac()\n                ssid = \"unknown\" if not ssid else ssid\n                # invalid mac is strange and should abort; ssid is ok\n                if not mac:\n                    raise ValueError(\"Mac can't be parsed from filename\")\n                pos_type = 'unknown'\n                if pos.type() == PositionFile.GPS:\n                    pos_type = 'gps'\n                elif pos.type() == PositionFile.GEO:\n                    pos_type = 'geo'\n                elif pos.type() == PositionFile.PAWGPS:\n                    pos_type = 'paw'\n                gps_data[ssid+\"_\"+mac] = {\n                    'ssid': ssid,\n                    'mac': mac,\n                    'type': pos_type,\n                    'lng': pos.lng(),\n                    'lat': pos.lat(),\n                    'acc': pos.accuracy(),\n                    'ts_first': pos.timestamp_first(),\n                    'ts_last': pos.timestamp_last(),\n                    }\n\n                # get ap password if exist\n                check_for = os.path.basename(pos_file).split(\".\")[0] + \".pcap.cracked\"\n                if check_for in all_files:\n                    gps_data[ssid + \"_\" + mac][\"pass\"] = pos.password()\n\n                self.ALREADY_SENT += pos_file\n            except json.JSONDecodeError as error:\n                self.SKIP += pos_file\n                logging.error(f\"[webgpsmap] JSONDecodeError in: {pos_file} - error: {error}\")\n                continue\n            except ValueError as error:\n                self.SKIP += pos_file\n                logging.error(f\"[webgpsmap] ValueError: {pos_file} - error: {error}\")\n                continue\n            except OSError as error:\n                self.SKIP += pos_file\n                logging.error(f\"[webgpsmap] OSError: {pos_file} - error: {error}\")\n                continue\n        logging.info(f\"[webgpsmap] loaded {len(gps_data)} positions\")\n        return gps_data\n\n    def get_html(self):\n        \"\"\"\n        Returns the html page\n        \"\"\"\n        try:\n            template_file = os.path.dirname(os.path.realpath(__file__)) + \"/\" + \"webgpsmap.html\"\n            html_data = open(template_file, \"r\").read()\n        except Exception as error:\n            logging.error(f\"[webgpsmap] error loading template file {template_file} - error: {error}\")\n        return html_data\n\n\nclass PositionFile:\n    \"\"\"\n    Wraps gps / net-pos files\n    \"\"\"\n    GPS = 1\n    GEO = 2\n    PAWGPS = 3\n\n    def __init__(self, path):\n        self._file = path\n        self._filename = os.path.basename(path)\n        try:\n            logging.debug(f\"[webgpsmap] loading {path}\")\n            with open(path, 'r') as json_file:\n                self._json = json.load(json_file)\n            logging.debug(f\"[webgpsmap] loaded {path}\")\n        except json.JSONDecodeError as js_e:\n            raise js_e\n\n    def mac(self):\n        \"\"\"\n        Returns the mac from filename\n        \"\"\"\n        parsed_mac = re.search(r'.*_?([a-zA-Z0-9]{12})\\.(?:gps|geo|paw-gps)\\.json', self._filename)\n        if parsed_mac:\n            mac = parsed_mac.groups()[0]\n            return mac\n        return None\n\n    def ssid(self):\n        \"\"\"\n        Returns the ssid from filename\n        \"\"\"\n        parsed_ssid = re.search(r'(.+)_[a-zA-Z0-9]{12}\\.(?:gps|geo|paw-gps)\\.json', self._filename)\n        if parsed_ssid:\n            return parsed_ssid.groups()[0]\n        return None\n\n\n    def json(self):\n        \"\"\"\n        returns the parsed json\n        \"\"\"\n        return self._json\n\n    def timestamp_first(self):\n        \"\"\"\n        returns the timestamp of AP first seen\n        \"\"\"\n        # use file timestamp creation time of the pcap file\n        return int(\"%.0f\" % os.path.getctime(self._file))\n\n    def timestamp_last(self):\n        \"\"\"\n        returns the timestamp of AP last seen\n        \"\"\"\n        return_ts = None\n        if 'ts' in self._json:\n            return_ts = self._json['ts']\n        elif 'Updated' in self._json:\n            # convert gps datetime to unix timestamp: \"2019-10-05T23:12:40.422996+01:00\"\n            dateObj = parse(self._json['Updated'])\n            return_ts = int(\"%.0f\" % dateObj.timestamp())\n        else:\n            # use file timestamp last modification of the json file\n            return_ts = int(\"%.0f\" % os.path.getmtime(self._file))\n        return return_ts\n\n    def password(self):\n        \"\"\"\n        returns the password from file.pcap.cracked or None\n        \"\"\"\n        return_pass = None\n        # 2do: make better filename split/remove extension because this one has problems with \".\" in path\n        base_filename, ext1, ext2 = re.split('\\.', self._file)\n        password_file_path = base_filename + \".pcap.cracked\"\n        if os.path.isfile(password_file_path):\n            try:\n                password_file = open(password_file_path, 'r')\n                return_pass = password_file.read()\n                password_file.close()\n            except OSError as error:\n                logging.error(f\"[webgpsmap] OS error loading password: {password_file_path} - error: {format(error)}\")\n            except:\n                logging.error(f\"[webgpsmap] Unexpected error loading password: {password_file_path} - error: {sys.exc_info()[0]}\")\n                raise\n        return return_pass\n\n    def type(self):\n        \"\"\"\n        returns the type of the file\n        \"\"\"\n        if self._file.endswith('.gps.json'):\n            return PositionFile.GPS\n        if self._file.endswith('.geo.json'):\n            return PositionFile.GEO\n        if self._file.endswith('.paw-gps.json'):\n            return PositionFile.PAWGPS\n        return None\n\n    def lat(self):\n        try:\n            lat = None\n            # try to get value from known formats\n            if 'Latitude' in self._json:\n                lat = self._json['Latitude']\n            if 'lat' in self._json:\n                lat = self._json['lat']  # an old paw-gps format: {\"long\": 14.693561, \"lat\": 40.806375}\n            if 'location' in self._json:\n                if 'lat' in self._json['location']:\n                    lat = self._json['location']['lat']\n            # check value\n            if lat is None:\n                raise ValueError(f\"Lat is None in {self._filename}\")\n            if lat == 0:\n                raise ValueError(f\"Lat is 0 in {self._filename}\")\n            return lat\n        except KeyError:\n            pass\n        return None\n\n    def lng(self):\n        try:\n            lng = None\n            # try to get value from known formats\n            if 'Longitude' in self._json:\n                lng = self._json['Longitude']\n            if 'long' in self._json:\n                lng = self._json['long']  # an old paw-gps format: {\"long\": 14.693561, \"lat\": 40.806375}\n            if 'location' in self._json:\n                if 'lng' in self._json['location']:\n                    lng = self._json['location']['lng']\n            # check value\n            if lng is None:\n                raise ValueError(f\"Lng is None in {self._filename}\")\n            if lng == 0:\n                raise ValueError(f\"Lng is 0 in {self._filename}\")\n            return lng\n        except KeyError:\n            pass\n        return None\n\n    def accuracy(self):\n        if self.type() == PositionFile.GPS:\n            return 50.0 # a default\n        if self.type() == PositionFile.PAWGPS:\n            return 50.0 # a default\n        if self.type() == PositionFile.GEO:\n            try:\n                return self._json['accuracy']\n            except KeyError:\n                pass\n        return None\n"
  },
  {
    "path": "pwnagotchi/plugins/default/wigle.py",
    "content": "import os\nimport logging\nimport json\nimport csv\nimport requests\n\nfrom io import StringIO\nfrom datetime import datetime\nfrom pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcap, StatusFile, remove_whitelisted\nfrom threading import Lock\nfrom pwnagotchi import plugins\nfrom pwnagotchi._version import __version__ as __pwnagotchi_version__\n\n\ndef _extract_gps_data(path):\n    \"\"\"\n    Extract data from gps-file\n\n    return json-obj\n    \"\"\"\n\n    try:\n        if path.endswith('.geo.json'):\n            with open(path, 'r') as json_file:\n                tempJson = json.load(json_file)\n                d = datetime.utcfromtimestamp(int(tempJson[\"ts\"]))\n                return {\"Latitude\": tempJson[\"location\"][\"lat\"], \"Longitude\": tempJson[\"location\"][\"lng\"], \"Altitude\": 10, \"Updated\": d.strftime('%Y-%m-%dT%H:%M:%S.%f')}\n        else:\n            with open(path, 'r') as json_file:\n                return json.load(json_file)\n    except OSError as os_err:\n        raise os_err\n    except json.JSONDecodeError as json_err:\n        raise json_err\n\n\ndef _format_auth(data):\n    out = \"\"\n    for auth in data:\n        out = f\"{out}[{auth}]\"\n    return out\n\n\ndef _transform_wigle_entry(gps_data, pcap_data, plugin_version):\n    \"\"\"\n    Transform to wigle entry in file\n    \"\"\"\n    dummy = StringIO()\n    # write kismet header\n    dummy.write(\n        \"WigleWifi-1.4,appRelease={},model=pwnagotchi,release={},device=pwnagotchi,display=kismet,board=kismet,brand=pwnagotchi\\n\".format(plugin_version, __pwnagotchi_version__))\n    dummy.write(\n        \"MAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\")\n\n    writer = csv.writer(dummy, delimiter=\",\", quoting=csv.QUOTE_NONE, escapechar=\"\\\\\")\n    writer.writerow([\n        pcap_data[WifiInfo.BSSID],\n        pcap_data[WifiInfo.ESSID],\n        _format_auth(pcap_data[WifiInfo.ENCRYPTION]),\n        datetime.strptime(gps_data['Updated'].rsplit('.')[0],\n                          \"%Y-%m-%dT%H:%M:%S\").strftime('%Y-%m-%d %H:%M:%S'),\n        pcap_data[WifiInfo.CHANNEL],\n        pcap_data[WifiInfo.RSSI],\n        gps_data['Latitude'],\n        gps_data['Longitude'],\n        gps_data['Altitude'],\n        0,  # accuracy?\n        'WIFI'])\n    return dummy.getvalue()\n\n\ndef _send_to_wigle(lines, api_key, donate=True, timeout=30):\n    \"\"\"\n    Uploads the file to wigle-net\n    \"\"\"\n\n    dummy = StringIO()\n\n    for line in lines:\n        dummy.write(f\"{line}\")\n\n    dummy.seek(0)\n\n    headers = {'Authorization': f\"Basic {api_key}\",\n               'Accept': 'application/json'}\n    data = {'donate': 'on' if donate else 'false'}\n    payload = {'file': dummy, 'type': 'text/csv'}\n    try:\n        res = requests.post('https://api.wigle.net/api/v2/file/upload',\n                            data=data,\n                            headers=headers,\n                            files=payload,\n                            timeout=timeout)\n        json_res = res.json()\n        if not json_res['success']:\n            raise requests.exceptions.RequestException(json_res['message'])\n    except requests.exceptions.RequestException as re_e:\n        raise re_e\n\n\nclass Wigle(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '2.0.0'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin automatically uploads collected wifis to wigle.net'\n\n    def __init__(self):\n        self.ready = False\n        self.report = StatusFile('/root/.wigle_uploads', data_format='json')\n        self.skip = list()\n        self.lock = Lock()\n\n    def on_loaded(self):\n        if 'api_key' not in self.options or ('api_key' in self.options and self.options['api_key'] is None):\n            logging.debug(\"WIGLE: api_key isn't set. Can't upload to wigle.net\")\n            return\n\n        if not 'whitelist' in self.options:\n            self.options['whitelist'] = list()\n\n        if not 'donate' in self.options:\n            self.options['donate'] = True\n\n        self.ready = True\n        logging.info(\"WIGLE: ready\")\n\n    def on_internet_available(self, agent):\n        \"\"\"\n        Called in manual mode when there's internet connectivity\n        \"\"\"\n        if not self.ready or self.lock.locked():\n            return\n\n        from scapy.all import Scapy_Exception\n\n        config = agent.config()\n        display = agent.view()\n        reported = self.report.data_field_or('reported', default=list())\n        handshake_dir = config['bettercap']['handshakes']\n        all_files = os.listdir(handshake_dir)\n        all_gps_files = [os.path.join(handshake_dir, filename)\n                         for filename in all_files\n                         if filename.endswith('.gps.json') or filename.endswith('.paw-gps.json') or filename.endswith('.geo.json')]\n\n        all_gps_files = remove_whitelisted(all_gps_files, self.options['whitelist'])\n        new_gps_files = set(all_gps_files) - set(reported) - set(self.skip)\n        if new_gps_files:\n            logging.info(\"WIGLE: Internet connectivity detected. Uploading new handshakes to wigle.net\")\n            csv_entries = list()\n            no_err_entries = list()\n            for gps_file in new_gps_files:\n                if gps_file.endswith('.gps.json'):\n                    pcap_filename = gps_file.replace('.gps.json', '.pcap')\n                if gps_file.endswith('.paw-gps.json'):\n                    pcap_filename = gps_file.replace('.paw-gps.json', '.pcap')\n                if gps_file.endswith('.geo.json'):\n                    pcap_filename = gps_file.replace('.geo.json', '.pcap')\n                if not os.path.exists(pcap_filename):\n                    logging.debug(\"WIGLE: Can't find pcap for %s\", gps_file)\n                    self.skip.append(gps_file)\n                    continue\n                try:\n                    gps_data = _extract_gps_data(gps_file)\n                except OSError as os_err:\n                    logging.debug(\"WIGLE: %s\", os_err)\n                    self.skip.append(gps_file)\n                    continue\n                except json.JSONDecodeError as json_err:\n                    logging.debug(\"WIGLE: %s\", json_err)\n                    self.skip.append(gps_file)\n                    continue\n                if gps_data['Latitude'] == 0 and gps_data['Longitude'] == 0:\n                    logging.debug(\"WIGLE: Not enough gps-information for %s. Trying again next time.\", gps_file)\n                    self.skip.append(gps_file)\n                    continue\n                try:\n                    pcap_data = extract_from_pcap(pcap_filename, [WifiInfo.BSSID,\n                                                                  WifiInfo.ESSID,\n                                                                  WifiInfo.ENCRYPTION,\n                                                                  WifiInfo.CHANNEL,\n                                                                  WifiInfo.RSSI])\n                except FieldNotFoundError:\n                    logging.debug(\"WIGLE: Could not extract all information. Skip %s\", gps_file)\n                    self.skip.append(gps_file)\n                    continue\n                except Scapy_Exception as sc_e:\n                    logging.debug(\"WIGLE: %s\", sc_e)\n                    self.skip.append(gps_file)\n                    continue\n                new_entry = _transform_wigle_entry(gps_data, pcap_data, self.__version__)\n                csv_entries.append(new_entry)\n                no_err_entries.append(gps_file)\n            if csv_entries:\n                display.on_uploading('wigle.net')\n\n                try:\n                    _send_to_wigle(csv_entries, self.options['api_key'], donate=self.options['donate'])\n                    reported += no_err_entries\n                    self.report.update(data={'reported': reported})\n                    logging.info(\"WIGLE: Successfully uploaded %d files\", len(no_err_entries))\n                except requests.exceptions.RequestException as re_e:\n                    self.skip += no_err_entries\n                    logging.debug(\"WIGLE: Got an exception while uploading %s\", re_e)\n                except OSError as os_e:\n                    self.skip += no_err_entries\n                    logging.debug(\"WIGLE: Got the following error: %s\", os_e)\n\n                display.on_normal()\n"
  },
  {
    "path": "pwnagotchi/plugins/default/wpa-sec.py",
    "content": "import os\nimport logging\nimport requests\nfrom datetime import datetime\nfrom threading import Lock\nfrom pwnagotchi.utils import StatusFile, remove_whitelisted\nfrom pwnagotchi import plugins\nfrom json.decoder import JSONDecodeError\n\n\nclass WpaSec(plugins.Plugin):\n    __author__ = '33197631+dadav@users.noreply.github.com'\n    __version__ = '2.1.0'\n    __license__ = 'GPL3'\n    __description__ = 'This plugin automatically uploads handshakes to https://wpa-sec.stanev.org'\n\n    def __init__(self):\n        self.ready = False\n        self.lock = Lock()\n        try:\n            self.report = StatusFile('/root/.wpa_sec_uploads', data_format='json')\n        except JSONDecodeError:\n            os.remove(\"/root/.wpa_sec_uploads\")\n            self.report = StatusFile('/root/.wpa_sec_uploads', data_format='json')\n        self.options = dict()\n        self.skip = list()\n\n    def _upload_to_wpasec(self, path, timeout=30):\n        \"\"\"\n        Uploads the file to https://wpa-sec.stanev.org, or another endpoint.\n        \"\"\"\n        with open(path, 'rb') as file_to_upload:\n            cookie = {'key': self.options['api_key']}\n            payload = {'file': file_to_upload}\n\n            try:\n                result = requests.post(self.options['api_url'],\n                                       cookies=cookie,\n                                       files=payload,\n                                       timeout=timeout)\n                if ' already submitted' in result.text:\n                    logging.debug(\"%s was already submitted.\", path)\n            except requests.exceptions.RequestException as req_e:\n                raise req_e\n\n\n    def _download_from_wpasec(self, output, timeout=30):\n        \"\"\"\n        Downloads the results from wpasec and safes them to output\n\n        Output-Format: bssid, station_mac, ssid, password\n        \"\"\"\n        api_url = self.options['api_url']\n        if not api_url.endswith('/'):\n            api_url = f\"{api_url}/\"\n        api_url = f\"{api_url}?api&dl=1\"\n\n        cookie = {'key': self.options['api_key']}\n        try:\n            result = requests.get(api_url, cookies=cookie, timeout=timeout)\n            with open(output, 'wb') as output_file:\n                output_file.write(result.content)\n        except requests.exceptions.RequestException as req_e:\n            raise req_e\n        except OSError as os_e:\n            raise os_e\n\n\n    def on_loaded(self):\n        \"\"\"\n        Gets called when the plugin gets loaded\n        \"\"\"\n        if 'api_key' not in self.options or ('api_key' in self.options and not self.options['api_key']):\n            logging.error(\"WPA_SEC: API-KEY isn't set. Can't upload to wpa-sec.stanev.org\")\n            return\n\n        if 'api_url' not in self.options or ('api_url' in self.options and not self.options['api_url']):\n            logging.error(\"WPA_SEC: API-URL isn't set. Can't upload, no endpoint configured.\")\n            return\n\n        if 'whitelist' not in self.options:\n            self.options['whitelist'] = list()\n\n        self.ready = True\n        logging.info(\"WPA_SEC: plugin loaded\")\n\n    def on_webhook(self, path, request):\n        from flask import make_response, redirect\n        response = make_response(redirect(self.options['api_url'], code=302))\n        response.set_cookie('key', self.options['api_key'])\n        return response\n\n    def on_internet_available(self, agent):\n        \"\"\"\n        Called in manual mode when there's internet connectivity\n        \"\"\"\n        if not self.ready or self.lock.locked():\n            return\n\n        with self.lock:\n            config = agent.config()\n            display = agent.view()\n            reported = self.report.data_field_or('reported', default=list())\n            handshake_dir = config['bettercap']['handshakes']\n            handshake_filenames = os.listdir(handshake_dir)\n            handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if\n                               filename.endswith('.pcap')]\n            handshake_paths = remove_whitelisted(handshake_paths, self.options['whitelist'])\n            handshake_new = set(handshake_paths) - set(reported) - set(self.skip)\n\n            if handshake_new:\n                logging.info(\"WPA_SEC: Internet connectivity detected. Uploading new handshakes to wpa-sec.stanev.org\")\n                for idx, handshake in enumerate(handshake_new):\n                    display.on_uploading(f\"wpa-sec.stanev.org ({idx + 1}/{len(handshake_new)})\")\n\n                    try:\n                        self._upload_to_wpasec(handshake)\n                        reported.append(handshake)\n                        self.report.update(data={'reported': reported})\n                        logging.debug(\"WPA_SEC: Successfully uploaded %s\", handshake)\n                    except requests.exceptions.RequestException as req_e:\n                        self.skip.append(handshake)\n                        logging.debug(\"WPA_SEC: %s\", req_e)\n                        continue\n                    except OSError as os_e:\n                        logging.debug(\"WPA_SEC: %s\", os_e)\n                        continue\n\n                display.on_normal()\n\n            if 'download_results' in self.options and self.options['download_results']:\n                cracked_file = os.path.join(handshake_dir, 'wpa-sec.cracked.potfile')\n                if os.path.exists(cracked_file):\n                    last_check = datetime.fromtimestamp(os.path.getmtime(cracked_file))\n                    if last_check is not None and ((datetime.now() - last_check).seconds / (60 * 60)) < 1:\n                        return\n                try:\n                    self._download_from_wpasec(os.path.join(handshake_dir, 'wpa-sec.cracked.potfile'))\n                    logging.info(\"WPA_SEC: Downloaded cracked passwords.\")\n                except requests.exceptions.RequestException as req_e:\n                    logging.debug(\"WPA_SEC: %s\", req_e)\n                except OSError as os_e:\n                    logging.debug(\"WPA_SEC: %s\", os_e)\n"
  },
  {
    "path": "pwnagotchi/ui/__init__.py",
    "content": "\n"
  },
  {
    "path": "pwnagotchi/ui/components.py",
    "content": "from PIL import Image\nfrom textwrap import TextWrapper\n\n\nclass Widget(object):\n    def __init__(self, xy, color=0):\n        self.xy = xy\n        self.color = color\n\n    def draw(self, canvas, drawer):\n        raise Exception(\"not implemented\")\n\n\nclass Bitmap(Widget):\n    def __init__(self, path, xy, color=0):\n        super().__init__(xy, color)\n        self.image = Image.open(path)\n\n    def draw(self, canvas, drawer):\n        canvas.paste(self.image, self.xy)\n\n\nclass Line(Widget):\n    def __init__(self, xy, color=0, width=1):\n        super().__init__(xy, color)\n        self.width = width\n\n    def draw(self, canvas, drawer):\n        drawer.line(self.xy, fill=self.color, width=self.width)\n\n\nclass Rect(Widget):\n    def draw(self, canvas, drawer):\n        drawer.rectangle(self.xy, outline=self.color)\n\n\nclass FilledRect(Widget):\n    def draw(self, canvas, drawer):\n        drawer.rectangle(self.xy, fill=self.color)\n\n\nclass Text(Widget):\n    def __init__(self, value=\"\", position=(0, 0), font=None, color=0, wrap=False, max_length=0):\n        super().__init__(position, color)\n        self.value = value\n        self.font = font\n        self.wrap = wrap\n        self.max_length = max_length\n        self.wrapper = TextWrapper(width=self.max_length, replace_whitespace=False) if wrap else None\n\n    def draw(self, canvas, drawer):\n        if self.value is not None:\n            if self.wrap:\n                text = '\\n'.join(self.wrapper.wrap(self.value))\n            else:\n                text = self.value\n            drawer.text(self.xy, text, font=self.font, fill=self.color)\n\n\nclass LabeledValue(Widget):\n    def __init__(self, label, value=\"\", position=(0, 0), label_font=None, text_font=None, color=0, label_spacing=5):\n        super().__init__(position, color)\n        self.label = label\n        self.value = value\n        self.label_font = label_font\n        self.text_font = text_font\n        self.label_spacing = label_spacing\n\n    def draw(self, canvas, drawer):\n        if self.label is None:\n            drawer.text(self.xy, self.value, font=self.label_font, fill=self.color)\n        else:\n            pos = self.xy\n            drawer.text(pos, self.label, font=self.label_font, fill=self.color)\n            drawer.text((pos[0] + self.label_spacing + 5 * len(self.label), pos[1]), self.value, font=self.text_font, fill=self.color)\n"
  },
  {
    "path": "pwnagotchi/ui/display.py",
    "content": "import os\nimport logging\nimport threading\n\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi.ui.hw as hw\nfrom pwnagotchi.ui.view import View\n\n\nclass Display(View):\n    def __init__(self, config, state={}):\n        super(Display, self).__init__(config, hw.display_for(config), state)\n        config = config['ui']['display']\n\n        self._enabled = config['enabled']\n        self._rotation = config['rotation']\n\n        self.init_display()\n\n        self._canvas_next_event = threading.Event()\n        self._canvas_next = None\n        self._render_thread_instance = threading.Thread(\n            target=self._render_thread,\n            daemon=True\n        )\n        self._render_thread_instance.start()\n\n    def is_inky(self):\n        return self._implementation.name == 'inky'\n\n    def is_papirus(self):\n        return self._implementation.name == 'papirus'\n\n    def is_waveshare_v1(self):\n        return self._implementation.name == 'waveshare_1'\n\n    def is_waveshare_v2(self):\n        return self._implementation.name == 'waveshare_2'\n\n    def is_waveshare_v3(self):\n        return self._implementation.name == 'waveshare_3'\n\n    def is_waveshare27inch(self):\n        return self._implementation.name == 'waveshare27inch'\n\n    def is_waveshare29inch(self):\n        return self._implementation.name == 'waveshare29inch'\n\n    def is_oledhat(self):\n        return self._implementation.name == 'oledhat'\n\n    def is_adafruitssd1306i2c(self):\n        return self._implementation.name == 'adafruitssd1306i2c'\n\n    def is_lcdhat(self):\n        return self._implementation.name == 'lcdhat'\n\n    def is_dfrobot_v1(self):\n        return self._implementation.name == 'dfrobot_v1'\n\n    def is_dfrobot_v2(self):\n        return self._implementation.name == 'dfrobot_v2'\n\n    def is_waveshare144lcd(self):\n        return self._implementation.name == 'waveshare144lcd'\n\n    def is_waveshare154inch(self):\n        return self._implementation.name == 'waveshare154inch'\n\n    def is_waveshare213d(self):\n        return self._implementation.name == 'waveshare213d'\n\n    def is_waveshare213bc(self):\n        return self._implementation.name == 'waveshare213bc'\n\n    def is_waveshare213inb_v4(self):\n        return self._implementation.name == 'waveshare213inb_v4'\n\n    def is_waveshare35lcd(self):\n        return self._implementation.name == 'waveshare35lcd'\n\n    def is_spotpear24inch(self):\n        return self._implementation.name == 'spotpear24inch'\n\n    def is_waveshare_any(self):\n        return self.is_waveshare_v1() or self.is_waveshare_v2()\n\n    def init_display(self):\n        if self._enabled:\n            self._implementation.initialize()\n            plugins.on('display_setup', self._implementation)\n        else:\n            logging.warning(\"display module is disabled\")\n        self.on_render(self._on_view_rendered)\n\n    def clear(self):\n        self._implementation.clear()\n\n    def image(self):\n        img = None\n        if self._canvas is not None:\n            img = self._canvas if self._rotation == 0 else self._canvas.rotate(-self._rotation)\n        return img\n\n    def _render_thread(self):\n        \"\"\"Used for non-blocking screen updating.\"\"\"\n\n        while True:\n            self._canvas_next_event.wait()\n            self._canvas_next_event.clear()\n            self._implementation.render(self._canvas_next)\n\n    def _on_view_rendered(self, img):\n        try:\n            if self._config['ui']['web']['on_frame'] != '':\n                os.system(self._config['ui']['web']['on_frame'])\n        except Exception as e:\n            logging.error(\"%s\" % e)\n\n        if self._enabled:\n            self._canvas = (img if self._rotation == 0 else img.rotate(self._rotation))\n            if self._implementation is not None:\n                self._canvas_next = self._canvas\n                self._canvas_next_event.set()\n"
  },
  {
    "path": "pwnagotchi/ui/faces.py",
    "content": "LOOK_R = '( ⚆_⚆)'\nLOOK_L = '(☉_☉ )'\nLOOK_R_HAPPY = '( ◕‿◕)'\nLOOK_L_HAPPY = '(◕‿◕ )'\nSLEEP = '(⇀‿‿↼)'\nSLEEP2 = '(≖‿‿≖)'\nAWAKE = '(◕‿‿◕)'\nBORED = '(-__-)'\nINTENSE = '(°▃▃°)'\nCOOL = '(⌐■_■)'\nHAPPY = '(•‿‿•)'\nGRATEFUL = '(^‿‿^)'\nEXCITED = '(ᵔ◡◡ᵔ)'\nMOTIVATED = '(☼‿‿☼)'\nDEMOTIVATED = '(≖__≖)'\nSMART = '(✜‿‿✜)'\nLONELY = '(ب__ب)'\nSAD = '(╥☁╥ )'\nANGRY = \"(-_-')\"\nFRIEND = '(♥‿‿♥)'\nBROKEN = '(☓‿‿☓)'\nDEBUG = '(#__#)'\nUPLOAD = '(1__0)'\nUPLOAD1 = '(1__1)'\nUPLOAD2 = '(0__1)'\n\ndef load_from_config(config):\n    for face_name, face_value in config.items():\n        globals()[face_name.upper()] = face_value\n"
  },
  {
    "path": "pwnagotchi/ui/fonts.py",
    "content": "from PIL import ImageFont\n\n# should not be changed\nFONT_NAME = 'DejaVuSansMono'\n\n# can be changed\nSTATUS_FONT_NAME = None\nSIZE_OFFSET = 0\n\nBold = None\nBoldSmall = None\nBoldBig = None\nMedium = None\nSmall = None\nHuge = None\n\n\ndef init(config):\n    global STATUS_FONT_NAME, SIZE_OFFSET\n    STATUS_FONT_NAME = config['ui']['font']['name']\n    SIZE_OFFSET = config['ui']['font']['size_offset']\n    setup(10, 8, 10, 25, 25, 9)\n\n\ndef status_font(old_font):\n    global STATUS_FONT_NAME, SIZE_OFFSET\n    return ImageFont.truetype(STATUS_FONT_NAME, size=old_font.size + SIZE_OFFSET)\n\n\ndef setup(bold, bold_small, medium, huge, bold_big, small):\n    global Bold, BoldSmall, Medium, Huge, BoldBig, Small, FONT_NAME\n\n    Small = ImageFont.truetype(FONT_NAME, small)\n    Medium = ImageFont.truetype(FONT_NAME, medium)\n    BoldSmall = ImageFont.truetype(\"%s-Bold\" % FONT_NAME, bold_small)\n    Bold = ImageFont.truetype(\"%s-Bold\" % FONT_NAME, bold)\n    BoldBig = ImageFont.truetype(\"%s-Bold\" % FONT_NAME, bold_big)\n    Huge = ImageFont.truetype(\"%s-Bold\" % FONT_NAME, huge)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/__init__.py",
    "content": "from pwnagotchi.ui.hw.inky import Inky\nfrom pwnagotchi.ui.hw.papirus import Papirus\nfrom pwnagotchi.ui.hw.oledhat import OledHat\nfrom pwnagotchi.ui.hw.adafruitssd1306i2c import AdafruitSSD1306i2c\nfrom pwnagotchi.ui.hw.lcdhat import LcdHat\nfrom pwnagotchi.ui.hw.dfrobot1 import DFRobotV1\nfrom pwnagotchi.ui.hw.dfrobot2 import DFRobotV2\nfrom pwnagotchi.ui.hw.waveshare1 import WaveshareV1\nfrom pwnagotchi.ui.hw.waveshare2 import WaveshareV2\nfrom pwnagotchi.ui.hw.waveshare3 import WaveshareV3\nfrom pwnagotchi.ui.hw.waveshare27inch import Waveshare27inch\nfrom pwnagotchi.ui.hw.waveshare29inch import Waveshare29inch\nfrom pwnagotchi.ui.hw.waveshare144lcd import Waveshare144lcd\nfrom pwnagotchi.ui.hw.waveshare154inch import Waveshare154inch\nfrom pwnagotchi.ui.hw.waveshare213d import Waveshare213d\nfrom pwnagotchi.ui.hw.waveshare213bc import Waveshare213bc\nfrom pwnagotchi.ui.hw.waveshare213inb_v4 import Waveshare213bV4\nfrom pwnagotchi.ui.hw.waveshare35lcd import Waveshare35lcd\nfrom pwnagotchi.ui.hw.spotpear24inch import Spotpear24inch\n\ndef display_for(config):\n    # config has been normalized already in utils.load_config\n    if config['ui']['display']['type'] == 'inky':\n        return Inky(config)\n\n    elif config['ui']['display']['type'] == 'papirus':\n        return Papirus(config)\n\n    if config['ui']['display']['type'] == 'oledhat':\n        return OledHat(config)\n\n    if config['ui']['display']['type'] == 'adafruitssd1306i2c':\n        return AdafruitSSD1306i2c(config)\n\n    if config['ui']['display']['type'] == 'lcdhat':\n        return LcdHat(config)\n\n    if config['ui']['display']['type'] == 'dfrobot_1':\n        return DFRobotV1(config)\n\n    if config['ui']['display']['type'] == 'dfrobot_2':\n        return DFRobotV2(config)\n\n    elif config['ui']['display']['type'] == 'waveshare_1':\n        return WaveshareV1(config)\n\n    elif config['ui']['display']['type'] == 'waveshare_2':\n        return WaveshareV2(config)\n\n    elif config['ui']['display']['type'] == 'waveshare_3':\n        return WaveshareV3(config)\n\n    elif config['ui']['display']['type'] == 'waveshare27inch':\n        return Waveshare27inch(config)\n\n    elif config['ui']['display']['type'] == 'waveshare29inch':\n        return Waveshare29inch(config)\n\n    elif config['ui']['display']['type'] == 'waveshare144lcd':\n        return Waveshare144lcd(config)\n\n    elif config['ui']['display']['type'] == 'waveshare154inch':\n        return Waveshare154inch(config)\n\n    elif config['ui']['display']['type'] == 'waveshare213d':\n        return Waveshare213d(config)\n\n    elif config['ui']['display']['type'] == 'waveshare213bc':\n        return Waveshare213bc(config)\n\n    elif config['ui']['display']['type'] == 'waveshare213inb_v4':\n        return Waveshare213bV4(config)\n\n    elif config['ui']['display']['type'] == 'waveshare35lcd':\n        return Waveshare35lcd(config)\n\n    elif config['ui']['display']['type'] == 'spotpear24inch':\n        return Spotpear24inch(config)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/adafruitssd1306i2c.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass AdafruitSSD1306i2c(DisplayImpl):\n    def __init__(self, config):\n        super(AdafruitSSD1306i2c, self).__init__(config, 'adafruitssd1306i2c')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(8, 8, 8, 8, 25, 9)\n        self._layout['width'] = 128\n        self._layout['height'] = 64\n        self._layout['face'] = (0, 32)\n        self._layout['name'] = (0, 10)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (25, 0)\n        self._layout['uptime'] = (65, 0)\n        self._layout['line1'] = [0, 9, 128, 9]\n        self._layout['line2'] = [0, 53, 128, 53]\n        self._layout['friend_face'] = (0, 41)\n        self._layout['friend_name'] = (40, 43)\n        self._layout['shakes'] = (0, 53)\n        self._layout['mode'] = (103, 10)\n        self._layout['status'] = {\n            'pos': (30, 18),\n            'font': fonts.status_font(fonts.Small),\n            'max': 18\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing adafruitssd1306i2c display\")\n        from pwnagotchi.ui.hw.libs.adafruit.adafruitssd1306i2c.epd import EPD\n        logging.info(\"EPD loaded\")\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear()\n\n    def render(self, canvas):\n        self._display.display(canvas)\n\n    def clear(self):\n        self._display.clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/base.py",
    "content": "import pwnagotchi.ui.fonts as fonts\n\n\nclass DisplayImpl(object):\n    def __init__(self, config, name):\n        self.name = name\n        self.config = config['ui']['display']\n        self._layout = {\n            'width': 0,\n            'height': 0,\n            'face': (0, 0),\n            'name': (0, 0),\n            'channel': (0, 0),\n            'aps': (0, 0),\n            'uptime': (0, 0),\n            'line1': (0, 0),\n            'line2': (0, 0),\n            'friend_face': (0, 0),\n            'friend_name': (0, 0),\n            'shakes': (0, 0),\n            'mode': (0, 0),\n            # status is special :D\n            'status': {\n                'pos': (0, 0),\n                'font': fonts.status_font(fonts.Medium),\n                'max': 20\n            }\n        }\n\n    def layout(self):\n        raise NotImplementedError\n\n    def initialize(self):\n        raise NotImplementedError\n\n    def render(self, canvas):\n        raise NotImplementedError\n\n    def clear(self):\n        raise NotImplementedError\n"
  },
  {
    "path": "pwnagotchi/ui/hw/dfrobot1.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\nclass DFRobotV1(DisplayImpl):\n  def __init__(self, config):\n    super(DFRobotV1, self).__init__(config, 'dfrobot_1')\n    self._display = None\n\n  def layout(self):\n    fonts.setup(10, 9, 10, 35, 25, 9)\n    self._layout['width'] = 250\n    self._layout['height'] = 122\n    self._layout['face'] = (0, 40)\n    self._layout['name'] = (5, 20)\n    self._layout['channel'] = (0, 0)\n    self._layout['aps'] = (28, 0)\n    self._layout['uptime'] = (185, 0)\n    self._layout['line1'] = [0, 14, 250, 14]\n    self._layout['line2'] = [0, 108, 250, 108]\n    self._layout['friend_face'] = (0, 92)\n    self._layout['friend_name'] = (40, 94)\n    self._layout['shakes'] = (0, 109)\n    self._layout['mode'] = (225, 109)\n    self._layout['status'] = {\n        'pos': (125, 20),\n        'font': fonts.status_font(fonts.Medium),\n        'max': 20\n    }\n    return self._layout\n\n  def initialize(self):\n    logging.info(\"initializing dfrobot1 display\")\n    from pwnagotchi.ui.hw.libs.dfrobot.v1.dfrobot import DFRobot\n    self._display = DFRobot()\n\n  def render(self, canvas):\n    buf = self._display.getbuffer(canvas)\n    self._display.display(buf)\n\n  def clear(self):\n    self._display.Clear(0xFF)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/dfrobot2.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\nclass DFRobotV2(DisplayImpl):\n  def __init__(self, config):\n    super(DFRobotV2, self).__init__(config, 'dfrobot_2')\n    self._display = None\n\n  def layout(self):\n    fonts.setup(10, 9, 10, 35, 25, 9)\n    self._layout['width'] = 250\n    self._layout['height'] = 122\n    self._layout['face'] = (0, 40)\n    self._layout['name'] = (5, 20)\n    self._layout['channel'] = (0, 0)\n    self._layout['aps'] = (28, 0)\n    self._layout['uptime'] = (185, 0)\n    self._layout['line1'] = [0, 14, 250, 14]\n    self._layout['line2'] = [0, 108, 250, 108]\n    self._layout['friend_face'] = (0, 92)\n    self._layout['friend_name'] = (40, 94)\n    self._layout['shakes'] = (0, 109)\n    self._layout['mode'] = (225, 109)\n    self._layout['status'] = {\n        'pos': (125, 20),\n        'font': fonts.status_font(fonts.Medium),\n        'max': 20\n    }\n    return self._layout\n\n  def initialize(self):\n    logging.info(\"initializing dfrobot2 display\")\n    from pwnagotchi.ui.hw.libs.dfrobot.v2.dfrobot import DFRobot\n    self._display = DFRobot()\n\n  def render(self, canvas):\n    buf = self._display.getbuffer(canvas)\n    self._display.display(buf)\n\n  def clear(self):\n    self._display.Clear(0xFF)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/inky.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Inky(DisplayImpl):\n    def __init__(self, config):\n        super(Inky, self).__init__(config, 'inky')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 8, 10, 28, 25, 9)\n        self._layout['width'] = 212\n        self._layout['height'] = 104\n        self._layout['face'] = (0, 37)\n        self._layout['name'] = (5, 18)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (30, 0)\n        self._layout['uptime'] = (147, 0)\n        self._layout['line1'] = [0, 12, 212, 12]\n        self._layout['line2'] = [0, 92, 212, 92]\n        self._layout['friend_face'] = (0, 76)\n        self._layout['friend_name'] = (40, 78)\n        self._layout['shakes'] = (0, 93)\n        self._layout['mode'] = (187, 93)\n        self._layout['status'] = {\n            'pos': (102, 18),\n            'font': fonts.status_font(fonts.Small),\n            'max': 20\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing inky display\")\n\n        if self.config['color'] == 'fastAndFurious':\n            logging.info(\"Initializing Inky in 2-color FAST MODE\")\n            logging.info(\"THIS MAY BE POTENTIALLY DANGEROUS. NO WARRANTY IS PROVIDED\")\n            logging.info(\"USE THIS DISPLAY IN THIS MODE AT YOUR OWN RISK\")\n\n            from pwnagotchi.ui.hw.libs.inkyphat.inkyphatfast import InkyPHATFast\n            self._display = InkyPHATFast('black')\n            self._display.set_border(InkyPHATFast.BLACK)\n        elif self.config['color'] == 'auto':\n            from inky.auto import auto\n            self._display = auto()\n            self._display.set_border(self._display.BLACK)\n            self._layout['width'] = self._display.WIDTH\n            self._layout['height'] = self._display.HEIGHT\n        else:\n            from inky import InkyPHAT\n            self._display = InkyPHAT(self.config['color'])\n            self._display.set_border(InkyPHAT.BLACK)\n\n    def render(self, canvas):\n        if self.config['color'] == 'black' or self.config['color'] == 'fastAndFurious':\n            display_colors = 2\n        else:\n            display_colors = 3\n\n        img_buffer = canvas.convert('RGB').convert('P', palette=1, colors=display_colors)\n        if self.config['color'] == 'red':\n            img_buffer.putpalette([\n                255, 255, 255,  # index 0 is white\n                0, 0, 0,  # index 1 is black\n                255, 0, 0  # index 2 is red\n            ])\n        elif self.config['color'] == 'yellow':\n            img_buffer.putpalette([\n                255, 255, 255,  # index 0 is white\n                0, 0, 0,  # index 1 is black\n                255, 255, 0  # index 2 is yellow\n            ])\n        else:\n            img_buffer.putpalette([\n                255, 255, 255,  # index 0 is white\n                0, 0, 0  # index 1 is black\n            ])\n\n        self._display.set_image(img_buffer)\n        try:\n            self._display.show()\n        except:\n            logging.exception(\"error while rendering on inky\")\n\n    def clear(self):\n        self._display.Clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/lcdhat.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass LcdHat(DisplayImpl):\n    def __init__(self, config):\n        super(LcdHat, self).__init__(config, 'lcdhat')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 9, 10, 35, 25, 9)\n        self._layout['width'] = 240\n        self._layout['height'] = 240\n        self._layout['face'] = (0, 40)\n        self._layout['name'] = (5, 20)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (28, 0)\n        self._layout['uptime'] = (175, 0)\n        self._layout['line1'] = [0, 14, 240, 14]\n        self._layout['line2'] = [0, 108, 240, 108]\n        self._layout['friend_face'] = (0, 92)\n        self._layout['friend_name'] = (40, 94)\n        self._layout['shakes'] = (0, 109)\n        self._layout['mode'] = (215, 109)\n        self._layout['status'] = {\n            'pos': (125, 20),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 20\n        }\n\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing lcdhat display\")\n        from pwnagotchi.ui.hw.libs.waveshare.lcdhat.epd import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.clear()\n\n    def render(self, canvas):\n        self._display.display(canvas)\n\n    def clear(self):\n        self._display.clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/adafruit/adafruitssd1306i2c/SSD1306.py",
    "content": "# Adaption of the Python driver for 0.96\" 128*64 i2c OLED displays,\n# based on the Adafruit driver without using any Adafruit dependency libraries,\n# instead it's using the usual smbus and RPi.GPIO\n# Adaptation made by: MD Raqibul Islam (github.com/erajtob)\n#\n# --\n# Copyright (c) 2014 Adafruit Industries\n# Author: Tony DiCola\n#\n# ******************************************************************************/\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\n\nimport logging\nimport RPi.GPIO as GPIO\nimport time\nfrom smbus import SMBus\n\nwidth = 128 #LCD width\nheight = 64  #LCD height\n\n# Constants\nSSD1306_I2C_ADDRESS = 0x3C    # 011110+SA0+RW - 0x3C or 0x3D\nSSD1306_SETCONTRAST = 0x81\nSSD1306_DISPLAYALLON_RESUME = 0xA4\nSSD1306_DISPLAYALLON = 0xA5\nSSD1306_NORMALDISPLAY = 0xA6\nSSD1306_INVERTDISPLAY = 0xA7\nSSD1306_DISPLAYOFF = 0xAE\nSSD1306_DISPLAYON = 0xAF\nSSD1306_SETDISPLAYOFFSET = 0xD3\nSSD1306_SETCOMPINS = 0xDA\nSSD1306_SETVCOMDETECT = 0xDB\nSSD1306_SETDISPLAYCLOCKDIV = 0xD5\nSSD1306_SETPRECHARGE = 0xD9\nSSD1306_SETMULTIPLEX = 0xA8\nSSD1306_SETLOWCOLUMN = 0x00\nSSD1306_SETHIGHCOLUMN = 0x10\nSSD1306_SETSTARTLINE = 0x40\nSSD1306_MEMORYMODE = 0x20\nSSD1306_COLUMNADDR = 0x21\nSSD1306_PAGEADDR = 0x22\nSSD1306_COMSCANINC = 0xC0\nSSD1306_COMSCANDEC = 0xC8\nSSD1306_SEGREMAP = 0xA0\nSSD1306_CHARGEPUMP = 0x8D\nSSD1306_EXTERNALVCC = 0x1\nSSD1306_SWITCHCAPVCC = 0x2\n\n# Scrolling constants\nSSD1306_ACTIVATE_SCROLL = 0x2F\nSSD1306_DEACTIVATE_SCROLL = 0x2E\nSSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3\nSSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26\nSSD1306_LEFT_HORIZONTAL_SCROLL = 0x27\nSSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29\nSSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A\n\nclass SSD1306Base(object):\n    def __init__(self, width, height, rst, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS, i2c=None):\n        self._i2c = None\n        self.width = width\n        self.height = height\n        self._pages = height//8\n        self._buffer = [0]*(width*self._pages)\n        if i2c_bus is None:\n            self._i2c = SMBus(1)\n        else:\n            self._i2c = SMBus(i2c_bus)\n        self._gpio = GPIO\n        self._gpio.setmode(GPIO.BCM)\n        self._gpio.setwarnings(False)\n        # Setup reset pin.\n        self._rst = rst\n        if not self._rst is None:\n            self._gpio.setup(self._rst, GPIO.OUT)\n\n    def _initialize(self):\n        raise NotImplementedError\n\n    def write8(self, register, value):\n        \"\"\"Write an 8-bit value to the specified register.\"\"\"\n        value = value & 0xFF\n        self._i2c.write_byte_data(SSD1306_I2C_ADDRESS, register, value)\n\n    def command(self, c):\n        \"\"\"Send command byte to display.\"\"\"\n        # I2C write.\n        control = 0x00   # Co = 0, DC = 0\n        self.write8(control, c)\n        time.sleep(0.01)\n\n    def data(self, c):\n        \"\"\"Send byte of data to display.\"\"\"\n        # I2C write.\n        control = 0x40   # Co = 0, DC = 0\n        self.write8(control, c)\n        time.sleep(0.01)\n\n    def begin(self, vccstate=SSD1306_SWITCHCAPVCC):\n        \"\"\"Initialize display.\"\"\"\n        # Save vcc state.\n        self._vccstate = vccstate\n        # Reset and initialize display.\n        self.reset()\n        self._initialize()\n        # Turn on the display.\n        self.command(SSD1306_DISPLAYON)\n\n    def reset(self):\n        \"\"\"Reset the display.\"\"\"\n        if self._rst is None:\n            return\n        # Set reset high for a millisecond.\n        GPIO.output(self._rst, GPIO.HIGH)\n        time.sleep(0.001)\n        # Set reset low for 10 milliseconds.\n        GPIO.output(self._rst, GPIO.LOW)\n        time.sleep(0.010)\n        # Set reset high again.\n        GPIO.output(self._rst, GPIO.HIGH)\n\n    def writeList(self, register, data):\n        \"\"\"Write bytes to the specified register.\"\"\"\n        self._i2c.write_i2c_block_data(SSD1306_I2C_ADDRESS, register, data)\n\n    def display(self):\n        \"\"\"Write display buffer to physical display.\"\"\"\n        self.command(SSD1306_COLUMNADDR)\n        self.command(0)              # Column start address. (0 = reset)\n        self.command(self.width-1)   # Column end address.\n        self.command(SSD1306_PAGEADDR)\n        self.command(0)              # Page start address. (0 = reset)\n        self.command(self._pages-1)  # Page end address.\n        # Write buffer data.\n        for i in range(0, len(self._buffer), 16):\n            control = 0x40   # Co = 0, DC = 0\n            # data = bytearray(len(self._buffer[i:i+16]) + 1)\n            # data[0] = control & 0xFF\n            # data[1:] = self._buffer[i:i+16]\n            self.writeList(control, self._buffer[i:i+16])\n\n    def image(self, image):\n        \"\"\"Set buffer to value of Python Imaging Library image.  The image should\n        be in 1 bit mode and a size equal to the display size.\n        \"\"\"\n        if image.mode != '1':\n            raise ValueError('Image must be in mode 1.')\n        imwidth, imheight = image.size\n        if imwidth != self.width or imheight != self.height:\n            raise ValueError('Image must be same dimensions as display ({0}x{1}).' \\\n                .format(self.width, self.height))\n        # Grab all the pixels from the image, faster than getpixel.\n        pix = image.load()\n        # Iterate through the memory pages\n        index = 0\n        for page in range(self._pages):\n            # Iterate through all x axis columns.\n            for x in range(self.width):\n                # Set the bits for the column of pixels at the current position.\n                bits = 0\n                # Don't use range here as it's a bit slow\n                for bit in [0, 1, 2, 3, 4, 5, 6, 7]:\n                    bits = bits << 1\n                    bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1\n                # Update buffer byte and increment to next byte.\n                self._buffer[index] = bits\n                index += 1\n\n    def clear(self):\n        \"\"\"Clear contents of image buffer.\"\"\"\n        self._buffer = [0]*(self.width*self._pages)\n\n    def set_contrast(self, contrast):\n        \"\"\"Sets the contrast of the display.  Contrast should be a value between\n        0 and 255.\"\"\"\n        if contrast < 0 or contrast > 255:\n            raise ValueError('Contrast must be a value from 0 to 255 (inclusive).')\n        self.command(SSD1306_SETCONTRAST)\n        self.command(contrast)\n\n    def dim(self, dim):\n        \"\"\"Adjusts contrast to dim the display if dim is True, otherwise sets the\n        contrast to normal brightness if dim is False.\n        \"\"\"\n        # Assume dim display.\n        contrast = 0\n        # Adjust contrast based on VCC if not dimming.\n        if not dim:\n            if self._vccstate == SSD1306_EXTERNALVCC:\n                contrast = 0x9F\n            else:\n                contrast = 0xCF\n            self.set_contrast(contrast)\n\nclass SSD1306_128_64(SSD1306Base):\n    def __init__(self, rst, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,\n                 i2c=None):\n        # Call base class constructor.\n        super(SSD1306_128_64, self).__init__(128, 64, rst, i2c_bus, i2c_address, i2c)\n\n    def _initialize(self):\n        # 128x64 pixel specific initialization.\n        self.command(SSD1306_DISPLAYOFF)                    # 0xAE\n        self.command(SSD1306_SETDISPLAYCLOCKDIV)            # 0xD5\n        self.command(0x80)                                  # the suggested ratio 0x80\n        self.command(SSD1306_SETMULTIPLEX)                  # 0xA8\n        self.command(0x3F)\n        self.command(SSD1306_SETDISPLAYOFFSET)              # 0xD3\n        self.command(0x0)                                   # no offset\n        self.command(SSD1306_SETSTARTLINE | 0x0)            # line #0\n        self.command(SSD1306_CHARGEPUMP)                    # 0x8D\n        if self._vccstate == SSD1306_EXTERNALVCC:\n            self.command(0x10)\n        else:\n            self.command(0x14)\n        self.command(SSD1306_MEMORYMODE)                    # 0x20\n        self.command(0x00)                                  # 0x0 act like ks0108\n        self.command(SSD1306_SEGREMAP | 0x1)\n        self.command(SSD1306_COMSCANDEC)\n        self.command(SSD1306_SETCOMPINS)                    # 0xDA\n        self.command(0x12)\n        self.command(SSD1306_SETCONTRAST)                   # 0x81\n        if self._vccstate == SSD1306_EXTERNALVCC:\n            self.command(0x9F)\n        else:\n            self.command(0xCF)\n        self.command(SSD1306_SETPRECHARGE)                  # 0xd9\n        if self._vccstate == SSD1306_EXTERNALVCC:\n            self.command(0x22)\n        else:\n            self.command(0xF1)\n        self.command(SSD1306_SETVCOMDETECT)                 # 0xDB\n        self.command(0x40)\n        self.command(SSD1306_DISPLAYALLON_RESUME)           # 0xA4\n        self.command(SSD1306_NORMALDISPLAY)                 # 0xA6\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/adafruit/adafruitssd1306i2c/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/adafruit/adafruitssd1306i2c/epd.py",
    "content": "from . import SSD1306\n\nRST = 24\n\ndisp = SSD1306.SSD1306_128_64(rst=RST, i2c_bus=1, i2c_address=0x3C)\n\nclass EPD(object):\n\n    def __init__(self, rst=RST, i2c_bus=None, i2c_address=0x3c):\n        self.width = 128\n        self.height = 64\n        if i2c_bus is None:\n            self.i2c_bus = 1\n        else:\n            self.i2c_bus = i2c_bus\n        self.i2c_address = i2c_address\n        self.disp = disp\n\n    def init(self):\n        self.disp.begin()\n\n    def Clear(self):\n        self.disp.clear()\n        self.disp.display()\n\n    def display(self, image):\n        self.disp.image(image)\n        self.disp.display()"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/LICENSE",
    "content": "                  GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 2.1, February 1999\n\n Copyright (C) 1991, 1999 Free Software Foundation, Inc.\n 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n[This is the first released version of the Lesser GPL.  It also counts\n as the successor of the GNU Library Public License, version 2, hence\n the version number 2.1.]\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicenses are intended to guarantee your freedom to share and change\nfree software--to make sure the software is free for all its users.\n\n  This license, the Lesser General Public License, applies to some\nspecially designated software packages--typically libraries--of the\nFree Software Foundation and other authors who decide to use it.  You\ncan use it too, but we suggest you first think carefully about whether\nthis license or the ordinary General Public License is the better\nstrategy to use in any particular case, based on the explanations below.\n\n  When we speak of free software, we are referring to freedom of use,\nnot price.  Our General Public Licenses are designed to make sure that\nyou have the freedom to distribute copies of free software (and charge\nfor this service if you wish); that you receive source code or can get\nit if you want it; that you can change the software and use pieces of\nit in new free programs; and that you are informed that you can do\nthese things.\n\n  To protect your rights, we need to make restrictions that forbid\ndistributors to deny you these rights or to ask you to surrender these\nrights.  These restrictions translate to certain responsibilities for\nyou if you distribute copies of the library or if you modify it.\n\n  For example, if you distribute copies of the library, whether gratis\nor for a fee, you must give the recipients all the rights that we gave\nyou.  You must make sure that they, too, receive or can get the source\ncode.  If you link other code with the library, you must provide\ncomplete object files to the recipients, so that they can relink them\nwith the library after making changes to the library and recompiling\nit.  And you must show them these terms so they know their rights.\n\n  We protect your rights with a two-step method: (1) we copyright the\nlibrary, and (2) we offer you this license, which gives you legal\npermission to copy, distribute and/or modify the library.\n\n  To protect each distributor, we want to make it very clear that\nthere is no warranty for the free library.  Also, if the library is\nmodified by someone else and passed on, the recipients should know\nthat what they have is not the original version, so that the original\nauthor's reputation will not be affected by problems that might be\nintroduced by others.\n\n  Finally, software patents pose a constant threat to the existence of\nany free program.  We wish to make sure that a company cannot\neffectively restrict the users of a free program by obtaining a\nrestrictive license from a patent holder.  Therefore, we insist that\nany patent license obtained for a version of the library must be\nconsistent with the full freedom of use specified in this license.\n\n  Most GNU software, including some libraries, is covered by the\nordinary GNU General Public License.  This license, the GNU Lesser\nGeneral Public License, applies to certain designated libraries, and\nis quite different from the ordinary General Public License.  We use\nthis license for certain libraries in order to permit linking those\nlibraries into non-free programs.\n\n  When a program is linked with a library, whether statically or using\na shared library, the combination of the two is legally speaking a\ncombined work, a derivative of the original library.  The ordinary\nGeneral Public License therefore permits such linking only if the\nentire combination fits its criteria of freedom.  The Lesser General\nPublic License permits more lax criteria for linking other code with\nthe library.\n\n  We call this license the \"Lesser\" General Public License because it\ndoes Less to protect the user's freedom than the ordinary General\nPublic License.  It also provides other free software developers Less\nof an advantage over competing non-free programs.  These disadvantages\nare the reason we use the ordinary General Public License for many\nlibraries.  However, the Lesser license provides advantages in certain\nspecial circumstances.\n\n  For example, on rare occasions, there may be a special need to\nencourage the widest possible use of a certain library, so that it becomes\na de-facto standard.  To achieve this, non-free programs must be\nallowed to use the library.  A more frequent case is that a free\nlibrary does the same job as widely used non-free libraries.  In this\ncase, there is little to gain by limiting the free library to free\nsoftware only, so we use the Lesser General Public License.\n\n  In other cases, permission to use a particular library in non-free\nprograms enables a greater number of people to use a large body of\nfree software.  For example, permission to use the GNU C Library in\nnon-free programs enables many more people to use the whole GNU\noperating system, as well as its variant, the GNU/Linux operating\nsystem.\n\n  Although the Lesser General Public License is Less protective of the\nusers' freedom, it does ensure that the user of a program that is\nlinked with the Library has the freedom and the wherewithal to run\nthat program using a modified version of the Library.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.  Pay close attention to the difference between a\n\"work based on the library\" and a \"work that uses the library\".  The\nformer contains code derived from the library, whereas the latter must\nbe combined with the library in order to run.\n\n                  GNU LESSER GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License Agreement applies to any software library or other\nprogram which contains a notice placed by the copyright holder or\nother authorized party saying it may be distributed under the terms of\nthis Lesser General Public License (also called \"this License\").\nEach licensee is addressed as \"you\".\n\n  A \"library\" means a collection of software functions and/or data\nprepared so as to be conveniently linked with application programs\n(which use some of those functions and data) to form executables.\n\n  The \"Library\", below, refers to any such software library or work\nwhich has been distributed under these terms.  A \"work based on the\nLibrary\" means either the Library or any derivative work under\ncopyright law: that is to say, a work containing the Library or a\nportion of it, either verbatim or with modifications and/or translated\nstraightforwardly into another language.  (Hereinafter, translation is\nincluded without limitation in the term \"modification\".)\n\n  \"Source code\" for a work means the preferred form of the work for\nmaking modifications to it.  For a library, complete source code means\nall the source code for all modules it contains, plus any associated\ninterface definition files, plus the scripts used to control compilation\nand installation of the library.\n\n  Activities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning a program using the Library is not restricted, and output from\nsuch a program is covered only if its contents constitute a work based\non the Library (independent of the use of the Library in a tool for\nwriting it).  Whether that is true depends on what the Library does\nand what the program that uses the Library does.\n\n  1. You may copy and distribute verbatim copies of the Library's\ncomplete source code as you receive it, in any medium, provided that\nyou conspicuously and appropriately publish on each copy an\nappropriate copyright notice and disclaimer of warranty; keep intact\nall the notices that refer to this License and to the absence of any\nwarranty; and distribute a copy of this License along with the\nLibrary.\n\n  You may charge a fee for the physical act of transferring a copy,\nand you may at your option offer warranty protection in exchange for a\nfee.\n\n  2. You may modify your copy or copies of the Library or any portion\nof it, thus forming a work based on the Library, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) The modified work must itself be a software library.\n\n    b) You must cause the files modified to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    c) You must cause the whole of the work to be licensed at no\n    charge to all third parties under the terms of this License.\n\n    d) If a facility in the modified Library refers to a function or a\n    table of data to be supplied by an application program that uses\n    the facility, other than as an argument passed when the facility\n    is invoked, then you must make a good faith effort to ensure that,\n    in the event an application does not supply such function or\n    table, the facility still operates, and performs whatever part of\n    its purpose remains meaningful.\n\n    (For example, a function in a library to compute square roots has\n    a purpose that is entirely well-defined independent of the\n    application.  Therefore, Subsection 2d requires that any\n    application-supplied function or table used by this function must\n    be optional: if the application does not supply it, the square\n    root function must still compute square roots.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Library,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Library, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote\nit.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Library.\n\nIn addition, mere aggregation of another work not based on the Library\nwith the Library (or with a work based on the Library) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may opt to apply the terms of the ordinary GNU General Public\nLicense instead of this License to a given copy of the Library.  To do\nthis, you must alter all the notices that refer to this License, so\nthat they refer to the ordinary GNU General Public License, version 2,\ninstead of to this License.  (If a newer version than version 2 of the\nordinary GNU General Public License has appeared, then you can specify\nthat version instead if you wish.)  Do not make any other change in\nthese notices.\n\n  Once this change is made in a given copy, it is irreversible for\nthat copy, so the ordinary GNU General Public License applies to all\nsubsequent copies and derivative works made from that copy.\n\n  This option is useful when you wish to copy part of the code of\nthe Library into a program that is not a library.\n\n  4. You may copy and distribute the Library (or a portion or\nderivative of it, under Section 2) in object code or executable form\nunder the terms of Sections 1 and 2 above provided that you accompany\nit with the complete corresponding machine-readable source code, which\nmust be distributed under the terms of Sections 1 and 2 above on a\nmedium customarily used for software interchange.\n\n  If distribution of object code is made by offering access to copy\nfrom a designated place, then offering equivalent access to copy the\nsource code from the same place satisfies the requirement to\ndistribute the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  5. A program that contains no derivative of any portion of the\nLibrary, but is designed to work with the Library by being compiled or\nlinked with it, is called a \"work that uses the Library\".  Such a\nwork, in isolation, is not a derivative work of the Library, and\ntherefore falls outside the scope of this License.\n\n  However, linking a \"work that uses the Library\" with the Library\ncreates an executable that is a derivative of the Library (because it\ncontains portions of the Library), rather than a \"work that uses the\nlibrary\".  The executable is therefore covered by this License.\nSection 6 states terms for distribution of such executables.\n\n  When a \"work that uses the Library\" uses material from a header file\nthat is part of the Library, the object code for the work may be a\nderivative work of the Library even though the source code is not.\nWhether this is true is especially significant if the work can be\nlinked without the Library, or if the work is itself a library.  The\nthreshold for this to be true is not precisely defined by law.\n\n  If such an object file uses only numerical parameters, data\nstructure layouts and accessors, and small macros and small inline\nfunctions (ten lines or less in length), then the use of the object\nfile is unrestricted, regardless of whether it is legally a derivative\nwork.  (Executables containing this object code plus portions of the\nLibrary will still fall under Section 6.)\n\n  Otherwise, if the work is a derivative of the Library, you may\ndistribute the object code for the work under the terms of Section 6.\nAny executables containing that work also fall under Section 6,\nwhether or not they are linked directly with the Library itself.\n\n  6. As an exception to the Sections above, you may also combine or\nlink a \"work that uses the Library\" with the Library to produce a\nwork containing portions of the Library, and distribute that work\nunder terms of your choice, provided that the terms permit\nmodification of the work for the customer's own use and reverse\nengineering for debugging such modifications.\n\n  You must give prominent notice with each copy of the work that the\nLibrary is used in it and that the Library and its use are covered by\nthis License.  You must supply a copy of this License.  If the work\nduring execution displays copyright notices, you must include the\ncopyright notice for the Library among them, as well as a reference\ndirecting the user to the copy of this License.  Also, you must do one\nof these things:\n\n    a) Accompany the work with the complete corresponding\n    machine-readable source code for the Library including whatever\n    changes were used in the work (which must be distributed under\n    Sections 1 and 2 above); and, if the work is an executable linked\n    with the Library, with the complete machine-readable \"work that\n    uses the Library\", as object code and/or source code, so that the\n    user can modify the Library and then relink to produce a modified\n    executable containing the modified Library.  (It is understood\n    that the user who changes the contents of definitions files in the\n    Library will not necessarily be able to recompile the application\n    to use the modified definitions.)\n\n    b) Use a suitable shared library mechanism for linking with the\n    Library.  A suitable mechanism is one that (1) uses at run time a\n    copy of the library already present on the user's computer system,\n    rather than copying library functions into the executable, and (2)\n    will operate properly with a modified version of the library, if\n    the user installs one, as long as the modified version is\n    interface-compatible with the version that the work was made with.\n\n    c) Accompany the work with a written offer, valid for at\n    least three years, to give the same user the materials\n    specified in Subsection 6a, above, for a charge no more\n    than the cost of performing this distribution.\n\n    d) If distribution of the work is made by offering access to copy\n    from a designated place, offer equivalent access to copy the above\n    specified materials from the same place.\n\n    e) Verify that the user has already received a copy of these\n    materials or that you have already sent this user a copy.\n\n  For an executable, the required form of the \"work that uses the\nLibrary\" must include any data and utility programs needed for\nreproducing the executable from it.  However, as a special exception,\nthe materials to be distributed need not include anything that is\nnormally distributed (in either source or binary form) with the major\ncomponents (compiler, kernel, and so on) of the operating system on\nwhich the executable runs, unless that component itself accompanies\nthe executable.\n\n  It may happen that this requirement contradicts the license\nrestrictions of other proprietary libraries that do not normally\naccompany the operating system.  Such a contradiction means you cannot\nuse both them and the Library together in an executable that you\ndistribute.\n\n  7. You may place library facilities that are a work based on the\nLibrary side-by-side in a single library together with other library\nfacilities not covered by this License, and distribute such a combined\nlibrary, provided that the separate distribution of the work based on\nthe Library and of the other library facilities is otherwise\npermitted, and provided that you do these two things:\n\n    a) Accompany the combined library with a copy of the same work\n    based on the Library, uncombined with any other library\n    facilities.  This must be distributed under the terms of the\n    Sections above.\n\n    b) Give prominent notice with the combined library of the fact\n    that part of it is a work based on the Library, and explaining\n    where to find the accompanying uncombined form of the same work.\n\n  8. You may not copy, modify, sublicense, link with, or distribute\nthe Library except as expressly provided under this License.  Any\nattempt otherwise to copy, modify, sublicense, link with, or\ndistribute the Library is void, and will automatically terminate your\nrights under this License.  However, parties who have received copies,\nor rights, from you under this License will not have their licenses\nterminated so long as such parties remain in full compliance.\n\n  9. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Library or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Library (or any work based on the\nLibrary), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Library or works based on it.\n\n  10. Each time you redistribute the Library (or any work based on the\nLibrary), the recipient automatically receives a license from the\noriginal licensor to copy, distribute, link with or modify the Library\nsubject to these terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties with\nthis License.\n\n  11. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Library at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Library by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Library.\n\nIf any portion of this section is held invalid or unenforceable under any\nparticular circumstance, the balance of the section is intended to apply,\nand the section as a whole is intended to apply in other circumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  12. If the distribution and/or use of the Library is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Library under this License may add\nan explicit geographical distribution limitation excluding those countries,\nso that distribution is permitted only in or among countries not thus\nexcluded.  In such case, this License incorporates the limitation as if\nwritten in the body of this License.\n\n  13. The Free Software Foundation may publish revised and/or new\nversions of the Lesser General Public License from time to time.\nSuch new versions will be similar in spirit to the present version,\nbut may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Library\nspecifies a version number of this License which applies to it and\n\"any later version\", you have the option of following the terms and\nconditions either of that version or of any later version published by\nthe Free Software Foundation.  If the Library does not specify a\nlicense version number, you may choose any version ever published by\nthe Free Software Foundation.\n\n  14. If you wish to incorporate parts of the Library into other free\nprograms whose distribution conditions are incompatible with these,\nwrite to the author to ask for permission.  For software which is\ncopyrighted by the Free Software Foundation, write to the Free\nSoftware Foundation; we sometimes make exceptions for this.  Our\ndecision will be guided by the two goals of preserving the free status\nof all derivatives of our free software and of promoting the sharing\nand reuse of software generally.\n\n                            NO WARRANTY\n\n  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\nWARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\nOTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY\nKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\nLIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\nTHE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\nWRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\nAND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\nFOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\nCONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nLIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\nRENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\nFAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\nSUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n           How to Apply These Terms to Your New Libraries\n\n  If you develop a new library, and you want it to be of the greatest\npossible use to the public, we recommend making it free software that\neveryone can redistribute and change.  You can do so by permitting\nredistribution under these terms (or, alternatively, under the terms of the\nordinary General Public License).\n\n  To apply these terms, attach the following notices to the library.  It is\nsafest to attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least the\n\"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the library's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n    USA\n\nAlso add information on how to contact you by electronic and paper mail.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the library, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the\n  library `Frob' (a library for tweaking knobs) written by James Random\n  Hacker.\n\n  <signature of Ty Coon>, 1 April 1990\n  Ty Coon, President of Vice\n\nThat's all there is to it!\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v1/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v1/dfrobot.py",
    "content": "# DFRobot display support\n\nimport logging\nfrom . import dfrobot_epaper\n\n#Resolution of display\nWIDTH = 250\nHEIGHT = 122\n\nRASPBERRY_SPI_BUS = 0\nRASPBERRY_SPI_DEV = 0\nRASPBERRY_PIN_CS = 27\nRASPBERRY_PIN_CD = 17\nRASPBERRY_PIN_BUSY = 4\n\nclass DFRobot:\n  def __init__(self):\n    self._display = dfrobot_epaper.DFRobot_Epaper_SPI(RASPBERRY_SPI_BUS, RASPBERRY_SPI_DEV, RASPBERRY_PIN_CS, RASPBERRY_PIN_CD, RASPBERRY_PIN_BUSY)\n    self._display.begin()\n    self.clear(0xFF)\n    self.FULL = self._display.FULL\n    self.PART = self._display.PART\n\n  def getbuffer(self, image):\n    if HEIGHT % 8 == 0:\n      linewidth = HEIGHT // 8\n    else:\n      linewidth = HEIGHT // 8 + 1\n\n    buf = [0xFF] * (linewidth * WIDTH)\n    image_monocolor = image.convert('1')\n    imwidth, imheight = image_monocolor.size\n    pixels = image_monocolor.load()\n\n    if (imwidth == HEIGHT and imheight == WIDTH):\n      for y in range(imheight):\n        for x in range(imwidth):\n          if pixels[x,y] == 0:\n            x = imwidth - x\n            buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8))\n    elif (imwidth == WIDTH and imheight == HEIGHT):\n      for y in range(imheight):\n        for x in range(imwidth):\n          newx = y\n          newy = WIDTH - x - 1\n          if pixels[x,y] == 0:\n            newy = imwidth - newy - 1\n            buf[newx // 8 + newy * linewidth] &= ~(0x80 >> (y % 8))\n    return buf\n  \n  def flush(self, type):\n    self._display.flush(type)\n\n  def display(self, buf):\n    self._display.setBuffer(buf)\n    self.flush(self._display.PART)\n\n  def clear(self, color):\n    if HEIGHT % 8 == 0:\n      linewidth = HEIGHT // 8\n    else:\n      linewidth = HEIGHT // 8 + 1\n\n    buf = [color] * (linewidth * WIDTH)\n    self._display.setBuffer(buf)\n    self.flush(self._display.FULL)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v1/dfrobot_epaper.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport time\n\nimport sys\nsys.path.append(\"..\")\n\n\ntry:\n  from .spi import SPI\n  from .gpio import GPIO\nexcept:\n  print(\"unknown platform\")\n  sys.exit()\n\nCONFIG_IL0376F = {\n\n}\n\nCONFIG_IL3895 = {\n  \n}\n\nclass DFRobot_Epaper:\n\n  XDOT = 128\n  YDOT = 250\n\n  FULL = True\n  PART = False\n\n  def __init__(self, width = 250, height = 122):\n    # length = width * height // 8\n    length = 4000\n    self._displayBuffer = bytearray(length)\n    i = 0\n    while i < length:\n      self._displayBuffer[i] = 0xff\n      i = i + 1\n\n    self._isBusy = False\n    self._busyExitEdge = GPIO.RISING\n\n  def _busyCB(self, channel):\n    self._isBusy = False\n\n  def setBusyExitEdge(self, edge):\n    if edge != GPIO.HIGH and edge != GPIO.LOW:\n      return\n    self._busyEdge = edge\n\n  def begin(self):\n    pass\n    # self.setBusyCB(self._busyCB)\n    # self._powerOn()\n\n  def setBuffer(self, buffer):\n    self._displayBuffer = buffer\n\n  def pixel(self, x, y, color):\n    if x < 0 or x >= self._width:\n      return\n    if y < 0 or y >= self._height:\n      return\n    x = int(x)\n    y = int(y)\n    m = int(x * 16 + (y + 1) / 8)\n    sy = int((y + 1) % 8)\n    if color == self.WHITE:\n      if sy != 0:\n        self._displayBuffer[m] = self._displayBuffer[m] | int(pow(2, 8 - sy))\n      else:\n        self._displayBuffer[m - 1] = self._displayBuffer[m - 1] | 1\n    elif color == self.BLACK:\n      if sy != 0:\n        self._displayBuffer[m] = self._displayBuffer[m] & (0xff - int(pow(2, 8 - sy)))\n      else:\n        self._displayBuffer[m - 1] = self._displayBuffer[m - 1] & 0xfe\n\n  def _setWindow(self, x, y):\n    hres = y // 8\n    hres = hres << 3\n    vres_h = x >> 8\n    vres_l = x & 0xff\n    self.writeCmdAndData(0x61, [hres, vres_h, vres_l])\n\n  def _initLut(self, mode):\n    if mode == self.FULL:\n      self.writeCmdAndData(0x32, [0x22,0x55,0xAA,0x55,0xAA,0x55,0xAA,\n                                  0x11,0x00,0x00,0x00,0x00,0x00,0x00,\n                                  0x00,0x00,0x1E,0x1E,0x1E,0x1E,0x1E,\n                                  0x1E,0x1E,0x1E,0x01,0x00,0x00,0x00,0x00])\n    elif mode == self.PART:\n      self.writeCmdAndData(0x32, [0x18,0x00,0x00,0x00,0x00,0x00,0x00,\n                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,\n                                  0x00,0x00,0x0F,0x01,0x00,0x00,0x00,\n                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])\n\n  def _setRamData(self, xStart, xEnd, yStart, yStart1, yEnd, yEnd1):\n    self.writeCmdAndData(0x44, [xStart, xEnd])\n    self.writeCmdAndData(0x45, [yStart, yStart1, yEnd, yEnd1])\n\n  def _setRamPointer(self, x, y, y1):\n    self.writeCmdAndData(0x4e, [x])\n    self.writeCmdAndData(0x4f, [y, y1])\n\n  def _init(self):\n    self.writeCmdAndData(0x01, [(self.YDOT - 1) % 256, (self.YDOT - 1) // 256, 0x00])\n    self.writeCmdAndData(0x0c, [0xd7, 0xd6, 0x9d])\n    self.writeCmdAndData(0x2c, [0xa8])\n    self.writeCmdAndData(0x3a, [0x1a])\n    self.writeCmdAndData(0x3b, [0x08])\n    self.writeCmdAndData(0x11, [0x01])\n    self._setRamData(0x00, (self.XDOT - 1) // 8, (self.YDOT - 1) % 256, (self.YDOT - 1) // 256, 0x00, 0x00)\n    self._setRamPointer(0x00, (self.YDOT - 1) % 256, (self.YDOT - 1) // 256)\n  \n  def _writeDisRam(self, sizeX, sizeY):\n    if sizeX % 8 != 0:\n      sizeX = sizeX + (8 - sizeX % 8)\n    sizeX = sizeX // 8\n    self.writeCmdAndData(0x24, self._displayBuffer[0: sizeX * sizeY])\n\n  def _updateDis(self, mode):\n    if mode == self.FULL:\n      self.writeCmdAndData(0x22, [0xc7])\n    elif mode == self.PART:\n      self.writeCmdAndData(0x22, [0x04])\n    else:\n      return\n    self.writeCmdAndData(0x20, [])\n    self.writeCmdAndData(0xff, [])\n\n  def _waitBusyExit(self):\n    temp = 0\n    while self.readBusy() != False:\n      time.sleep(0.01)\n      temp = temp + 1\n      if (temp % 200) == 0:\n        print(\"waitBusyExit\")\n\n  def _powerOn(self):\n    self.writeCmdAndData(0x22, [0xc0])\n    self.writeCmdAndData(0x20, [])\n\n  def _powerOff(self):\n    self.writeCmdAndData(0x12, [])\n    self.writeCmdAndData(0x82, [0x00])\n    self.writeCmdAndData(0x01, [0x02, 0x00, 0x00, 0x00, 0x00])\n    self.writeCmdAndData(0x02, [])\n\n  def _disPart(self, xStart, xEnd, yStart, yEnd):\n    self._setRamData(xStart // 8, xEnd // 8, yEnd % 256, yEnd // 256, yStart % 256, yStart // 256)\n    self._setRamPointer(xStart // 8, yEnd % 256, yEnd // 256)\n    self._writeDisRam(xEnd - xStart, yEnd - yStart + 1)\n    self._updateDis(self.PART)\n\n  def flush(self, mode):\n    if mode != self.FULL and mode != self.PART:\n      return\n    self._init()\n    self._initLut(mode)\n    self._powerOn()\n    if mode == self.PART:\n      self._disPart(0, self.XDOT - 1, 0, self.YDOT - 1)\n    else:\n      self._setRamPointer(0x00, (self.YDOT - 1) % 256, (self.YDOT - 1) // 256)\n      self._writeDisRam(self.XDOT, self.YDOT)\n      self._updateDis(mode)\n  \n  def startDrawBitmapFile(self, x, y):\n    self._bitmapFileStartX = x\n    self._bitmapFileStartY = y\n\n  def bitmapFileHelper(self, buf):\n    for i in range(len(buf) // 3):\n      addr = i * 3\n      if buf[addr] == 0x00 and buf[addr + 1] == 0x00 and buf[addr + 2] == 0x00:\n        self.pixel(self._bitmapFileStartX, self._bitmapFileStartY, self.BLACK)\n      else:\n        self.pixel(self._bitmapFileStartX, self._bitmapFileStartY, self.WHITE)\n      self._bitmapFileStartX += 1\n  \n  def endDrawBitmapFile(self):\n    self.flush(self.PART)\n\nclass DFRobot_Epaper_SPI(DFRobot_Epaper):\n\n  def __init__(self, bus, dev, cs, cd, busy):\n    DFRobot_Epaper.__init__(self)\n    self._spi = SPI(bus, dev)\n    self._cs = GPIO(cs, GPIO.OUT)\n    self._cd = GPIO(cd, GPIO.OUT)\n    self._busy = GPIO(busy, GPIO.IN)\n  \n  def writeCmdAndData(self, cmd, data = []):\n    self._waitBusyExit()\n    self._cs.setOut(GPIO.LOW)\n    self._cd.setOut(GPIO.LOW)\n    self._spi.transfer([cmd])\n    self._cd.setOut(GPIO.HIGH)\n    self._spi.transfer(data)\n    self._cs.setOut(GPIO.HIGH)\n\n  def readBusy(self):\n    return self._busy.read()\n\n  def setBusyCB(self, cb):\n    self._busy.setInterrupt(self._busyExitEdge, cb)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v1/gpio.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport time\nimport RPi.GPIO as RPIGPIO\n\nRPIGPIO.setmode(RPIGPIO.BCM)\nRPIGPIO.setwarnings(False)\n\nclass GPIO:\n\n  HIGH = RPIGPIO.HIGH\n  LOW = RPIGPIO.LOW\n\n  OUT = RPIGPIO.OUT\n  IN = RPIGPIO.IN\n\n  RISING = RPIGPIO.RISING\n  FALLING = RPIGPIO.FALLING\n  BOTH = RPIGPIO.BOTH\n\n  def __init__(self, pin, mode, defaultOut = HIGH):\n    self._pin = pin\n    self._fInt = None\n    self._intDone = True\n    self._intMode = None\n    if mode == self.OUT:\n      RPIGPIO.setup(pin, mode)\n      if defaultOut == self.HIGH:\n        RPIGPIO.output(pin, defaultOut)\n      else:\n        RPIGPIO.output(pin, self.LOW)\n    else:\n      RPIGPIO.setup(pin, self.IN, pull_up_down = RPIGPIO.PUD_UP)\n\n  def setOut(self, level):\n    if level:\n      RPIGPIO.output(self._pin, self.HIGH)\n    else:\n      RPIGPIO.output(self._pin, self.LOW)\n\n  def _intCB(self, status):\n    if self._intDone:\n      self._intDone = False\n      time.sleep(0.02)\n      if self._intMode == self.BOTH:\n        self._fInt()\n      elif self._intMode == self.RISING and self.read() == self.HIGH:\n        self._fInt()\n      elif self._intMode == self.FALLING and self.read() == self.LOW:\n        self._fInt()\n      self._intDone = True\n\n  def setInterrupt(self, mode, cb):\n    if mode != self.RISING and mode != self.FALLING and mode != self.BOTH:\n      return\n    self._intMode = mode\n    RPIGPIO.add_event_detect(self._pin, mode, self._intCB)\n    self._fInt = cb\n\n  def read(self):\n    return RPIGPIO.input(self._pin)\n  \n  def cleanup(self):\n    RPIGPIO.cleanup()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v1/spi.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport spidev\n\nclass SPI:\n\n  MODE_1 = 1\n  MODE_2 = 2\n  MODE_3 = 3\n  MODE_4 = 4\n\n  def __init__(self, bus, dev, speed = 3900000, mode = MODE_4):\n    self._bus = spidev.SpiDev()\n    self._bus.open(bus, dev)\n    self._bus.no_cs = True\n    self._bus.max_speed_hz = speed\n\n  def transfer(self, buf):\n    if len(buf):\n      return self._bus.xfer(buf)\n    return []\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/dfrobot.py",
    "content": "# DFRobot display support\n\nimport logging\nfrom . import dfrobot_epaper\n\n#Resolution of display\nWIDTH = 250\nHEIGHT = 122\n\nRASPBERRY_SPI_BUS = 0\nRASPBERRY_SPI_DEV = 0\nRASPBERRY_PIN_CS = 27\nRASPBERRY_PIN_CD = 17\nRASPBERRY_PIN_BUSY = 4\n\nclass DFRobot:\n  def __init__(self):\n    self._display = dfrobot_epaper.DFRobot_Epaper_SPI(RASPBERRY_SPI_BUS, RASPBERRY_SPI_DEV, RASPBERRY_PIN_CS, RASPBERRY_PIN_CD, RASPBERRY_PIN_BUSY)\n    self._display.begin()\n    self.clear(0xFF)\n    self.FULL = self._display.FULL\n    self.PART = self._display.PART\n\n  def getbuffer(self, image):\n    if HEIGHT % 8 == 0:\n      linewidth = HEIGHT // 8\n    else:\n      linewidth = HEIGHT // 8 + 1\n\n    buf = [0xFF] * (linewidth * WIDTH)\n    image_monocolor = image.convert('1')\n    imwidth, imheight = image_monocolor.size\n    pixels = image_monocolor.load()\n\n    if (imwidth == HEIGHT and imheight == WIDTH):\n      for y in range(imheight):\n        for x in range(imwidth):\n          if pixels[x,y] == 0:\n            x = imwidth - x\n            buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8))\n    elif (imwidth == WIDTH and imheight == HEIGHT):\n      for y in range(imheight):\n        for x in range(imwidth):\n          newx = y\n          newy = WIDTH - x - 1\n          if pixels[x,y] == 0:\n            newy = imwidth - newy - 1\n            buf[newx // 8 + newy * linewidth] &= ~(0x80 >> (y % 8))\n    return buf\n  \n  def flush(self, type):\n    self._display.flush(type)\n\n  def display(self, buf):\n    self._display.setBuffer(buf)\n    self.flush(self._display.PART)\n\n  def clear(self, color):\n    if HEIGHT % 8 == 0:\n      linewidth = HEIGHT // 8\n    else:\n      linewidth = HEIGHT // 8 + 1\n\n    buf = [color] * (linewidth * WIDTH)\n    self._display.setBuffer(buf)\n    self.flush(self._display.FULL)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/dfrobot_display/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/dfrobot_display/dfrobot_display.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport sys\n\nfrom .dfrobot_printString import PrintString\nfrom .dfrobot_fonts import Fonts\n\ndef color24to16(color):\n    return (((color >> 8) & 0xf800) | ((color >> 5) & 0x7e0) | ((color >> 3) & 0x1f))\n\ndef color16to24(color):\n    return (((color & 0xf800) << 8) | ((color & 0x7e0) << 5) | ((color & 0x1f) << 3))\n\ndef swap(o1, o2):\n    return (o2, o1)\n\nclass DFRobot_Display(PrintString):\n\n  WHITE24 = 0xffffff\n  SILVER24 = 0xc0c0c0\n  GRAY24 = 0x808080\n  BLACK24 = 0x000000\n  RED24 = 0xff0000\n  MAROON24 = 0x800000\n  YELLOW24 = 0xffff00\n  OLIVE24 = 0x808000\n  GREEN24 = 0x00ff00\n  DARKGREEN24 = 0x008000\n  CYAN24 = 0x00ffff\n  BLUE24 = 0x0000ff\n  NAVY24 = 0x000080\n  FUCHSIA24 = 0xff00ff\n  PURPLE24 = 0x800080\n  TEAL24 = 0x008080\n\n  WHITE16 = color24to16(WHITE24)\n  SILVER16 = color24to16(SILVER24)\n  GRAY16 = color24to16(GRAY24)\n  BLACK16 = color24to16(BLACK24)\n  RED16 = color24to16(RED24)\n  MAROON16 = color24to16(MAROON24)\n  YELLOW16 = color24to16(YELLOW24)\n  OLIVE16 = color24to16(OLIVE24)\n  GREEN16 = color24to16(GREEN24)\n  DARKGREEN16 = color24to16(DARKGREEN24)\n  CYAN16 = color24to16(CYAN24)\n  BLUE16 = color24to16(BLUE24)\n  NAVY16 = color24to16(NAVY24)\n  FUCHSIA16 = color24to16(FUCHSIA24)\n  PURPLE16 = color24to16(PURPLE24)\n  TEAL16 = color24to16(TEAL24)\n\n  WHITE = WHITE16\n  SILVER = SILVER16\n  GRAY = GRAY16\n  BLACK = BLACK16\n  RED = RED16\n  MAROON = MAROON16\n  YELLOW = YELLOW16\n  OLIVE = OLIVE16\n  GREEN = GREEN16\n  DARKGREEN = DARKGREEN16\n  CYAN = CYAN16\n  BLUE = BLUE16\n  NAVY = NAVY16\n  FUCHSIA = FUCHSIA16\n  PURPLE = PURPLE16\n  TEAL = TEAL16\n\n  POSITIVE = 1\n  REVERSE = -1\n\n  BITMAP_TBMLLR = \"TBMLLR\"\n  BITMAP_TBMRLL = \"TBMRLL\"\n  BITMAP_BTMLLR = \"BTMLLR\"\n  BITMAP_BTMRLL = \"BTMRLL\"\n  BITMAP_LRMTLB = \"LRMTLB\"\n  BITMAP_LRMBLT = \"LRMBLT\"\n  BITMAP_RLMTLB = \"RLMTLB\"\n  BIMTAP_RLMBLT = \"RLMBLT\"\n  BITMAP_UNKNOW = \"UNKNOW\"\n\n  def __init__(self, w, h):\n    PrintString.__init__(self)\n    print(\"DFRobot_Display init \" + str(w) + \" \" + str(h))\n    self._width = w\n    self._height = h\n\n    self._lineWidth = 1\n    self._bitmapSize = 1\n    self._bitmapFmt = \"\"\n    self._bmpFmt = self.BITMAP_TBMLLR\n\n    self._fonts = Fonts()\n    self._textSize = 1\n    self._textColor = self.BLACK\n    self._textBackground = self.WHITE\n    self._textCursorX = 0\n    self._textCursorY = 0\n    self._textIntervalRow = 0\n    self._textIntervalCol = 0\n\n  def _ternaryExpression(self, condition, o1, o2):\n    if condition:\n      return o1\n    return o2\n\n  def _getDirection(self, value):\n    if value >= 0:\n      return 1\n    return -1\n\n  def color16to24(self, color):\n    return color16to24(color)\n\n  def color24to16(self, color):\n    return color24to16(color)\n\n  def setColorTo16(self):\n    self.WHITE = self.WHITE16\n    self.SILVER = self.SILVER16\n    self.GRAY = self.GRAY16\n    self.BLACK = self.BLACK16\n    self.RED = self.RED16\n    self.MAROON = self.MAROON16\n    self.YELLOW = self.YELLOW16\n    self.OLIVE = self.OLIVE16\n    self.GREEN = self.GREEN16\n    self.DARKGREEN = self.DARKGREEN16\n    self.CYAN = self.CYAN16\n    self.BLUE = self.BLUE16\n    self.NAVY = self.NAVY16\n    self.FUCHSIA = self.FUCHSIA16\n    self.PURPLE = self.PURPLE16\n    self.TEAL = self.TEAL16\n\n  def setColorTo24(self):\n    self.WHITE = self.WHITE24\n    self.SILVER = self.SILVER24\n    self.GRAY = self.GRAY24\n    self.BLACK = self.BLACK24\n    self.RED = self.RED24\n    self.MAROON = self.MAROON24\n    self.YELLOW = self.YELLOW24\n    self.OLIVE = self.OLIVE24\n    self.GREEN = self.GREEN24\n    self.DARKGREEN = self.DARKGREEN24\n    self.CYAN = self.CYAN24\n    self.BLUE = self.BLUE24\n    self.NAVY = self.NAVY24\n    self.FUCHSIA = self.FUCHSIA24\n    self.PURPLE = self.PURPLE24\n    self.TEAL = self.TEAL24\n\n  def setLineWidth(self, w):\n    if w < 0:\n      return\n    self._lineWidth = w\n\n  def setTextFormat(self, size, color, background, intervalRow = 2, intervalCol = 0):\n    self._textColor = color\n    self._textIntervalRow = intervalRow\n    self._textIntervalCol = intervalCol\n    self._textBackground = background\n    if size < 0:\n      return\n    self._textSize = size\n\n  def setTextCursor(self, x, y):\n    self._textCursorX = int(x)\n    self._textCursorY = int(y)\n\n  def setBitmapSize(self, size):\n    if size < 0:\n      return\n    self._bitmapSize = size\n\n  def setBitmapFmt(self, fmt):\n    self._bmpFmt = fmt\n\n  def setExFonts(self, obj):\n    self._fonts.setExFonts(obj)\n\n  def setExFontsFmt(self, width, height):\n    self._fonts.setExFontsFmt(width, height)\n    \n  def setEnableDefaultFonts(self, opt):\n    self._fonts.setEnableDefaultFonts(opt)\n\n  def pixel(self, x, y, color):\n    pass\n\n  def clear(self, color):\n    self.fillRect(0, 0, self._width, self._height, color)\n    self._textCursorX = 0\n    self._textCursorY = 0\n\n  def VLine(self, x, y, h, color):\n    x = int(x)\n    y = int(y)\n    h = int(h)\n    direction = self._getDirection(h)\n    x -= self._lineWidth // 2\n    h = self._ternaryExpression(h > 0, h, -h)\n    for i in range(self._ternaryExpression(h > 0, h, - h)):\n      xx = x\n      for j in range(self._lineWidth):\n        self.pixel(xx, y, color)\n        xx += 1\n      y += direction\n\n  def HLine(self, x, y, w, color):\n    x = int(x)\n    y = int(y)\n    w = int(w)\n    direction = self._getDirection(w)\n    y -= self._lineWidth // 2\n    for i in range(self._ternaryExpression(w > 0, w, - w)):\n      yy = y\n      for j in range(self._lineWidth):\n        self.pixel(x, yy, color)\n        yy += 1\n      x += direction\n\n  def line(self, x, y, x1, y1, color):\n    x = int(x)\n    y = int(y)\n    x1 = int(x1)\n    y1 = int(y1)\n    if x == x1:\n      self.VLine(x, y, y1 - y, color)\n      return\n    if y == y1:\n      self.HLine(x, y, x1 - x, color)\n      return\n    dx = abs(x1 - x)\n    dy = abs(y1 - y)\n    dirX = self._ternaryExpression(x < x1, 1, -1)\n    dirY = self._ternaryExpression(y < y1, 1, -1)\n    if dx > dy:\n      err = dx / 2\n      for i in range(dx):\n        self.HLine(x, y, 1, color)\n        x += dirX\n        err -= dy\n        if err < 0:\n          err += dx\n          y += dirY\n      self.HLine(x1, y1, 1, color)\n    else:\n      err = dy / 2\n      for i in range(dy):\n        self.VLine(x, y, 1, color)\n        y += dirY\n        err -= dx\n        if err < 0:\n          err += dy\n          x += dirX\n      self.VLine(x1, y1, 1, color)\n\n  def triangle(self, x, y, x1, y1, x2, y2, color):\n    self.line(x, y, x1, y1, color)\n    self.line(x1, y1, x2, y2, color)\n    self.line(x2, y2, x, y, color)\n\n  def fillTriangle(self, x, y, x1, y1, x2, y2, color):\n    self.line(x, y, x1, y1, color)\n    self.line(x1, y1, x2, y2, color)\n    self.line(x2, y2, x, y, color)\n    x = int(x)\n    y = int(y)\n    x1 = int(x1)\n    y1 = int(y1)\n    x2 = int(x2)\n    y2 = int(y2)\n    temp = self._lineWidth\n    self._lineWidth = 1\n    if x == x1 and x == x2:\n      ymax = max([y, y1, y2])\n      ymin = min([y, y1, y2])\n      self.HLine(x, ymin, ymax - ymin, color)\n      self._lineWidth = temp\n      return\n    if y == y1 and y == y2:\n      xmax = max([x, x1, x2])\n      xmin = max([x, x1, x2])\n      self.VLine(xmin, y, xmax - xmin, color)\n      self._lineWidth = temp\n      return\n\n    direction = self.POSITIVE\n    if y == y1 or y1 == y2 or y == y2:\n      if y == y1:\n        (x, x2) = swap(x, x2)\n        (y, y2) = swap(y, y2)\n      elif y == y2:\n        (x, x1) = swap(x, x1)\n        (y, y1) = swap(y, y1)\n      if y > y1:\n        direction = self.REVERSE\n      if x1 > x2:\n        (x1, x2) = swap(x1, x2)\n        (y1, y2) = swap(y1, y2)\n    else:\n      if y > y1:\n        (x, x1) = swap(x, x1)\n        (y, y1) = swap(y, y1)\n      if y > y2:\n        (x, x2) = swap(x, x2)\n        (y, y2) = swap(y, y2)\n      if y1 > y2:\n        (x1, x2) = swap(x1, x2)\n        (y1, y2) = swap(y1, y2)\n\n    dx1 = x1 - x\n    dx2 = x2 - x\n    dx3 = x2 - x1\n    dy1 = y1 - y\n    dy2 = y2 - y\n    dy3 = y2 - y1\n    if direction == self.POSITIVE:\n      for i in range(dy1):\n        self.HLine(x + dx1 * i / dy1, y + i, (x + dx2 * i / dy2) - (x + dx1 * i / dy1) + 1, color)\n      for i in range(dy3):\n        self.HLine(x1 + dx3 * i / dy3, y1 + i, (x + dx2 * (i + dy1) / dy2) - (x1 + dx3 * i / dy3) + 1, color)\n    else:\n      y = y1 + dy1\n      dy1 = - dy1\n      for i in range(dy1):\n        self.HLine(x + dx1 * i / dy1, y1 + dy1 - i, (x + dx2 * i / dy1) - (x + dx1 * i / dy1) + 1, color)\n    self._lineWidth = temp\n\n  def rect(self, x, y, w, h, color):\n    if w < 0:\n      x += w\n      w = -w\n    if h < 0:\n      y += h\n      h = -h\n    self.HLine(x - self._lineWidth // 2, y, w + self._lineWidth, color)\n    self.HLine(x - self._lineWidth // 2, y + h, w + self._lineWidth, color)\n    self.VLine(x, y - self._lineWidth // 2, h + self._lineWidth, color)\n    self.VLine(x + w, y - self._lineWidth // 2, h + self._lineWidth, color)\n\n  def fillRect(self, x, y, w, h, color):\n    temp = self._lineWidth\n    self._lineWidth = 1\n    if w < 0:\n      x += w\n      w = abs(w)\n    for i in range(w):\n      self.VLine(x + i, y, h, color)\n    self._lineWidth = temp\n\n  QUADRANT_1 = 1\n  QUADRANT_2 = 2\n  QUADRANT_3 = 4\n  QUADRANT_4 = 8\n  QUADRANT_ALL = 15\n\n  def circleHelper(self, x, y, r, quadrant, color):\n    x = int(x)\n    y = int(y)\n    r = abs(int(r))\n    vx = 0\n    vy = r\n    dx = 1\n    dy = -2 * r\n    p = 1 - r\n    if quadrant & self.QUADRANT_1:\n      self.VLine(x + r, y, 1, color)\n    if quadrant & self.QUADRANT_2:\n      self.VLine(x, y - r, 1, color)\n    if quadrant & self.QUADRANT_3:\n      self.VLine(x - r, y, 1, color)\n    if quadrant & self.QUADRANT_4:\n      self.VLine(x, y + r, 1, color)\n    \n    halfLineWidth = self._lineWidth // 2\n    while vx < vy:\n      if p >= 0:\n        vy -= 1\n        dy += 2\n        p += dy\n      vx += 1\n      dx += 2\n      p += dx\n      if quadrant & self.QUADRANT_1:\n        self.fillRect(x + vx - halfLineWidth, y - vy - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 1\n        self.fillRect(x + vy - halfLineWidth, y - vx - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 1\n      if quadrant & self.QUADRANT_2:\n        self.fillRect(x - vx - halfLineWidth, y - vy - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 2\n        self.fillRect(x - vy - halfLineWidth, y - vx - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 2\n      if quadrant & self.QUADRANT_3:\n        self.fillRect(x - vx - halfLineWidth, y + vy - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 3\n        self.fillRect(x - vy - halfLineWidth, y + vx - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 3\n      if quadrant & self.QUADRANT_4:\n        self.fillRect(x + vx - halfLineWidth, y + vy - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 4\n        self.fillRect(x + vy - halfLineWidth, y + vx - halfLineWidth, self._lineWidth, self._lineWidth, color)  # quadrant 4\n\n  def circle(self, x, y, r, color):\n    self.circleHelper(x, y, r, self.QUADRANT_ALL, color)\n\n  def fillCircleHelper(self, x, y, r, quadrant, color):\n    x = int(x)\n    y = int(y)\n    r = abs(int(r))\n    temp = self._lineWidth\n    self._lineWidth = 1\n    vx = 0\n    vy = r\n    dx = 1\n    dy = -2 * r\n    p = 1 - r\n    if quadrant & self.QUADRANT_1:\n      self.HLine(x, y, r + 1, color)\n    if quadrant & self.QUADRANT_2:\n      self.VLine(x, y, - r - 1, color)\n    if quadrant & self.QUADRANT_3:\n      self.HLine(x, y, - r - 1, color)\n    if quadrant & self.QUADRANT_4:\n      self.VLine(x, y, r + 1, color)\n\n    while vx < vy:\n      if p >= 0:\n        vy -= 1\n        dy += 2\n        p += dy\n      vx += 1\n      dx += 2\n      p += dx\n      if quadrant & self.QUADRANT_1:\n        self.VLine(x + vx, y - vy, vy, color)  # quadrant 1\n        self.VLine(x + vy, y - vx, vx, color)  # quadrant 1\n      if quadrant & self.QUADRANT_2:\n        self.VLine(x - vx, y - vy, vy, color)  # quadrant 2\n        self.VLine(x - vy, y - vx, vx, color)  # quadrant 2\n      if quadrant & self.QUADRANT_3:\n        self.VLine(x - vx, y + vy, - vy, color)  # quadrant 3\n        self.VLine(x - vy, y + vx, - vx, color)  # quadrant 3\n      if quadrant & self.QUADRANT_4:\n        self.VLine(x + vx, y + vy, - vy, color)  # quadrant 4\n        self.VLine(x + vy, y + vx, - vx, color)  # quadrant 4\n    self._lineWidth = temp\n\n  def fillCircle(self, x, y, r, color):\n    self.fillCircleHelper(x, y, r, self.QUADRANT_ALL, color)\n\n  def roundRect(self, x, y, w, h, r, color):\n    x = int(x)\n    y = int(y)\n    w = int(w)\n    h = int(h)\n    r = abs(int(r))\n    if w < 0:\n      x += w\n      w = abs(w)\n    if h < 0:\n      y += h\n      h = abs(h)\n    self.HLine(x + r, y, w - 2 * r + 1, color)\n    self.HLine(x + r, y + h, w - 2 * r + 1, color)\n    self.VLine(x, y + r, h - 2 * r + 1, color)\n    self.VLine(x + w, y + r, h - 2 * r + 1, color)\n    self.circleHelper(x + r, y + r, r, self.QUADRANT_2, color)\n    self.circleHelper(x + w - r, y + r, r, self.QUADRANT_1, color)\n    self.circleHelper(x + r, y + h - r, r, self.QUADRANT_3, color)\n    self.circleHelper(x + w - r, y + h - r, r, self.QUADRANT_4, color)\n\n  def fillRoundRect(self, x, y, w, h, r, color):\n    x = int(x)\n    y = int(y)\n    w = int(w)\n    h = int(h)\n    r = abs(int(r))\n    if w < 0:\n      x += w\n      w = abs(w)\n    if h < 0:\n      y += h\n      h = abs(h)\n    self.fillRect(x + r, y, w - 2 * r, h, color)\n    self.fillRect(x, y + r, r, h - 2 * r, color)\n    self.fillRect(x + w - r, y + r, r, h - 2 * r, color)\n    self.fillCircleHelper(x + r, y + r, r, self.QUADRANT_2, color)\n    self.fillCircleHelper(x + w - r - 1, y + r, r, self.QUADRANT_1, color)\n    self.fillCircleHelper(x + r, y + h - r - 1, r, self.QUADRANT_3, color)\n    self.fillCircleHelper(x + w - r - 1, y + h - r - 1, r, self.QUADRANT_4, color)\n\n  def _bitmapHelper(self, increaseAxis, staticAxis, data, dataBit, exchange, color, background):\n    for i in data:\n      for j in range(8):\n        if i & dataBit:\n          if exchange:\n            self.fillRect(staticAxis, increaseAxis, self._bitmapSize, self._bitmapSize, color)\n          else:\n            self.fillRect(increaseAxis, staticAxis, self._bitmapSize, self._bitmapSize, color)\n        else:\n          if exchange:\n            self.fillRect(staticAxis, increaseAxis, self._bitmapSize, self._bitmapSize, background)\n          else:\n            self.fillRect(increaseAxis, staticAxis, self._bitmapSize, self._bitmapSize, background)\n        increaseAxis += self._bitmapSize\n        if dataBit & 0x80:\n          i <<= 1\n        else:\n          i >>= 1\n\n  def bitmap(self, x, y, bitmap, w, h, color, background):\n    if w < 0 or h < 0:\n      return\n    x = abs(int(x))\n    y = abs(int(y))\n\n    if self._bmpFmt == self.BITMAP_TBMLLR:\n      oneLineDataLen = (w - 1) // 8 + 1\n      for i in range(h):\n        yMask = y + i * self._bitmapSize\n        self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, False, color, background)\n    elif self._bmpFmt == self.BITMAP_TBMRLL:\n      oneLineDataLen = (w - 1) // 8 + 1\n      for i in range(h):\n        yMask = y + i * self._bitmapSize\n        self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, False, color, background)\n    elif self._bmpFmt == self.BITMAP_BTMLLR:\n      oneLineDataLen = (w - 1) // 8 + 1\n      for i in range(h):\n        yMask = y + h * self._bitmapSize - i * self._bitmapSize\n        self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, False, color, background)\n    elif self._bmpFmt == self.BITMAP_BTMRLL:\n      oneLineDataLen = (w - 1) // 8 + 1\n      for i in range(h):\n        yMask = y + h * self._bitmapSize - i * self._bitmapSize\n        self._bitmapHelper(x, yMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, False, color, background)\n    elif self._bmpFmt == self.BITMAP_LRMTLB:\n      oneLineDataLen = (h - 1) // 8 + 1\n      for i in range(w):\n        xMask = x + i * self._bitmapSize\n        self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, True, color, background)\n    elif self._bmpFmt == self.BITMAP_LRMBLT:\n      oneLineDataLen = (h - 1) // 8 + 1\n      for i in range(w):\n        xMask = x + i * self._bitmapSize\n        self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, True, color, background)\n    elif self._bmpFmt == self.BITMAP_RLMTLB:\n      oneLineDataLen = (h - 1) // 8 + 1\n      for i in range(w):\n        xMask = x + w * self._bitmapSize - i * self._bitmapSize\n        self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x80, True, color, background)\n    elif self._bmpFmt == self.BIMTAP_RLMBLT:\n      oneLineDataLen = (h - 1) // 8 + 1\n      for i in range(w):\n        xMask = x + w * self._bitmapSize - i * self._bitmapSize\n        self._bitmapHelper(y, xMask, bitmap[i * oneLineDataLen : oneLineDataLen * (i + 1)], 0x01, True, color, background)\n\n  def _bytesToNumber(self, data):\n    r = 0\n    i = len(data)\n    while i > 0:\n      i -= 1\n      r = r << 8 | data[i]\n    return r\n\n  def _getQuads(self, data, count):\n    r = []\n    for i in range(count):\n      r.append(data[i * 4 + 54 : i * 4 + 58])\n    return r\n\n  BITMAP_COMPRESSION_NO = 0\n  BITMAP_COMPRESSION_RLE8 = 1\n  BITMAP_COMPRESSION_RLE4 = 2\n  BITMAP_COMPRESSION_FIELDS = 3\n\n  def startDrawBitmapFile(self, x, y):\n    pass\n  \n  def bitmapFileHelper(self, buf):\n    pass\n\n  def endDrawBitmapFile(self):\n    pass\n\n  def bitmapFile(self, x, y, path):\n    try:\n      f = open(path, \"rb\")\n    except:\n      print(\"open file error\")\n      return\n    c = bytearray(f.read())\n    f.close()\n    if c[0] != 0x42 and c[1] != 0x4d:\n      print(\"file error\")\n      print(c[0])\n      print(c[1])\n      return\n    DIBOffset = self._bytesToNumber(c[10:14])\n    width = self._bytesToNumber(c[18:22])\n    height = self._bytesToNumber(c[22:26])\n    colorBits = self._bytesToNumber(c[28:30])\n    compression = self._bytesToNumber(c[30:32])\n    # print(\"w: %d, h: %d, colorBits: %d\" %(width, height, colorBits))\n\n    if colorBits == 24:\n      width3 = width * 3\n      for i in range(height):\n        self.startDrawBitmapFile(x, y + height - i)\n        buf = []\n        left = DIBOffset + i * width3\n        i = 0\n        while i < width3:\n          buf.append(c[left + i + 2])\n          buf.append(c[left + i + 1])\n          buf.append(c[left + i + 0])\n          i += 3\n        self.bitmapFileHelper(buf)\n      self.endDrawBitmapFile()\n\n    elif colorBits == 1:\n      quads = self._getQuads(c, 2)\n      addr = DIBOffset\n      if compression == self.BITMAP_COMPRESSION_NO:\n        addrCountComplement = (width // 8 + 1) % 4\n        if addrCountComplement != 0:\n          addrCountComplement = 4 - addrCountComplement\n        for i in range(height):\n          w = width\n          addrCount = 0\n          self.startDrawBitmapFile(x, y + height - i - 1)\n          buf = []\n          while w > 0:\n            d = c[addr + addrCount]\n            addrCount = addrCount + 1\n            j = 8\n            while w > 0 and j > 0:\n              j -= 1\n              quad = d & (0x01 << j)\n              if quad > 0:\n                quad = 1\n              buf.append(quads[quad][2])\n              buf.append(quads[quad][1])\n              buf.append(quads[quad][0])\n              w -= 1\n          self.bitmapFileHelper(buf)\n          addrCount += addrCountComplement\n          addr += addrCount\n        self.endDrawBitmapFile()\n    else:\n      print(\"dont support this bitmap file format yet\")\n\n  def writeOneChar(self, c):\n    if len(c) > 1:\n      c = c[0]\n    (l, width, height, fmt) = self._fonts.getOneCharacter(c)\n    temp = self._bmpFmt\n    self._bmpFmt = fmt\n    ts = self._textSize\n    if ord(c) == ord(\"\\n\"):\n      self._textCursorX = 0\n      self._textCursorY += height * ts + self._textIntervalCol\n    elif len(l):\n      temp1 = self._bitmapSize\n      self._bitmapSize = ts\n      self._textCursorX += self._textIntervalRow\n      if self._textCursorX + ts * width > self._width:\n        self.fillRect(self._textCursorX, self._textCursorY, self._width - self._textCursorX, self._fonts._extensionFontsHeight * ts + self._textIntervalCol, self._textBackground)\n        self._textCursorX = self._textIntervalRow\n        self._textCursorY += ts * self._fonts._extensionFontsHeight + self._textIntervalCol\n      self.fillRect(self._textCursorX, self._textCursorY, self._fonts._extensionFontsWidth * ts + self._textIntervalRow, self._fonts._extensionFontsHeight * ts + self._textIntervalCol, self._textBackground)\n      self.bitmap(self._textCursorX, self._textCursorY, l, width, height, self._textColor, self._textBackground)\n      self._textCursorX += ts * width\n      self._bitmapSize = temp1\n    self._bmpFmt = temp\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/dfrobot_display/dfrobot_fonts.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport json\n\nclass Fonts:\n\n  def __init__(self):\n    self._haveFontsABC = False\n    self._fontsABC = {}\n    self._fontsABCWidth = 0\n    self._fontsABCHeight = 0\n    self._fontsABCFmt = \"\"\n\n    self._haveExtensionFonts = False\n    self._extensionFontsWidth = 0\n    self._extensionFontsHeight = 0\n    \n    self._enableDefaultFonts = True\n\n  def setFontsABC(self, fonts):\n    self._haveFontsABC = True\n    self._fontsABC = fonts.fonts\n    self._fontsABCWidth = fonts.width\n    self._fontsABCHeight = fonts.height\n    self._fontsABCFmt = fonts.fmt\n    \n    self._extensionFontsWidth = fonts.width * 2\n    self._extensionFontsHeight = fonts.height * 2\n\n  def setExFonts(self, obj):\n    self._haveExtensionFonts = True\n    self._extensionFonts = obj\n    self._enableDefaultFonts = False\n  \n  def setEnableDefaultFonts(self, opt):\n    if opt:\n      self._enableDefaultFonts = True\n    else:\n      self._enableDefaultFonts = False\n\n  def setExFontsFmt(self, width, height):\n    if self._haveExtensionFonts:\n      self._extensionFonts.setFmt(width, height)\n      self._extensionFontsWidth = width\n      self._extensionFontsHeight = height\n\n  def getOneCharacter(self, c):\n    w = 0\n    h = 0\n    fmt = \"UNKNOW\"\n    rslt = []\n    done = False\n    if self._haveFontsABC and self._enableDefaultFonts:\n      try:\n        rslt = self._fontsABC[c]\n        w = self._fontsABCWidth\n        h = self._fontsABCHeight\n        fmt = self._fontsABCFmt\n        done = True\n      except:\n        # print(\"try get fonts ABC faild\")\n        pass\n    if self._haveExtensionFonts and done == False:\n      try:\n        (rslt, w, h, fmt) = self._extensionFonts.getOne(c)\n        done = True\n      except:\n        print(\"try get unicode fonts faild: %s\" %(c))\n    return (rslt, w, h, fmt)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/dfrobot_display/dfrobot_printString.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport sys\n\nclass PrintString:\n\n  def __init__(self):\n    pass\n\n  def writeOneChar(self, ch):\n    pass\n\n  def printStr(self, c):\n    try:\n      c = str(c)\n    except:\n      return\n    if sys.version_info.major == 2:\n      c = c.decode(\"utf-8\")\n    for i in c:\n      self.writeOneChar(i)\n\n  def printStrLn(self, c):\n    self.printStr(c)\n    self.writeOneChar(\"\\n\")\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/dfrobot_epaper.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport time\n\nimport sys\nsys.path.append(\"..\")\nimport RPi.GPIO as RPIGPIO\nfrom .dfrobot_display.dfrobot_display import DFRobot_Display\nfrom .display_extension import fonts_8_16 as fonts_ABC\n\ntry:\n  from .spi import SPI\n  from .gpio import GPIO\nexcept:\n  print(\"unknow platform\")\n  exit()\n\nCONFIG_IL0376F = {\n\n}\n\nCONFIG_IL3895 = {\n  \n}\n\nclass DFRobot_Epaper(DFRobot_Display):\n\n  XDOT = 128\n  YDOT = 250\n\n  FULL = True\n  PART = False\n\n  def __init__(self, width = 250, height = 122):\n    DFRobot_Display.__init__(self, width, height)\n    # length = width * height // 8\n    length = 4000\n    self._displayBuffer = bytearray(length)\n    i = 0\n    while i < length:\n      self._displayBuffer[i] = 0xff\n      i = i + 1\n\n    self._isBusy = False\n    self._busyExitEdge = GPIO.RISING\n    \n    self._fonts.setFontsABC(fonts_ABC)\n    self.setExFontsFmt(16, 16)\n\n  def _busyCB(self, channel):\n    self._isBusy = False\n\n  def setBusyExitEdge(self, edge):\n    if edge != GPIO.HIGH and edge != GPIO.LOW:\n      return\n    self._busyEdge = edge\n\n  def begin(self):\n    pass\n    #self._init()\n    #self._powerOn()\n    #self.setBusyCB(self._busyCB)\n    #self._powerOn()\n\n  def setBuffer(self, buffer):\n    self._displayBuffer = buffer\n\n  def pixel(self, x, y, color):\n    if x < 0 or x >= self._width:\n      return\n    if y < 0 or y >= self._height:\n      return\n    x = int(x)\n    y = int(y)\n    m = int(x * 16 + (y + 1) / 8)\n    sy = int((y + 1) % 8)\n    if color == self.WHITE:\n      if sy != 0:\n        self._displayBuffer[m] = self._displayBuffer[m] | int(pow(2, 8 - sy))\n      else:\n        self._displayBuffer[m - 1] = self._displayBuffer[m - 1] | 1\n    elif color == self.BLACK:\n      if sy != 0:\n        self._displayBuffer[m] = self._displayBuffer[m] & (0xff - int(pow(2, 8 - sy)))\n      else:\n        self._displayBuffer[m - 1] = self._displayBuffer[m - 1] & 0xfe\n\n  def _initLut(self, mode):\n    if mode == self.FULL:\n      self.writeCmdAndData(0x32, [  0xA0,\t0x90,\t0x50,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0x50,\t0x90,\t0xA0,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0xA0,\t0x90,\t0x50,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0x50,\t0x90,\t0xA0,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n\t\n                                    0x0F,\t0x0F,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x0F,\t0x0F,\t0x00,\t0x00,\t0x03,\t\t\n                                    0x0F,\t0x0F,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t \n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                  ])\n    elif mode == self.PART:\n      self.writeCmdAndData(0x32, [0xA0,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\n                                  0x50,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,0x00,\t0x00,\t0x00,\t0x00,\t\n                                  0xA0,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\n                                  0x50,\t0x00, 0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\n                                  0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t0x00, 0x00,\t0x00,\t\n\t\n                                    0x0f,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x0,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x0,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t \n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n                                    0x00,\t0x00,\t0x00,\t0x00,\t0x00,\t\t\n\t\t\t\t\t\t\t\t\t\t              ])\n\n  def _setRamData(self, xStart, xEnd, yStart, yStart1, yEnd, yEnd1):\n    self.writeCmdAndData(0x44, [xStart, xEnd])\n    self.writeCmdAndData(0x45, [yStart, yStart1, yEnd, yEnd1])\n\n  def _setRamPointer(self, x, y, y1):\n    self.writeCmdAndData(0x4e, [x])\n    self.writeCmdAndData(0x4f, [y, y1])\n\n  def _init(self,mode):\n      self.writeCmdAndData(0x12, [])\n      self.writeCmdAndData(0x01, [0xf9, 0x00, 0x00])\n      self.writeCmdAndData(0x74, [0x54])\n      self.writeCmdAndData(0x7e, [0x3b])\n      self.writeCmdAndData(0x11, [0x01])\n      self._setRamData(0x00, 0x0f, 0xf9,0x00, 0x00, 0x00)\n      self.writeCmdAndData(0x3c, [0x03])   \n      self._setRamPointer(0x00, 0xf9, 0x00)  \n      self.writeCmdAndData(0x21, [0x08])\n      self.writeCmdAndData(0x2c, [0x50])\n      self.writeCmdAndData(0x03, [0x15])\n      self.writeCmdAndData(0x04, [0x41,0xa8,0x32])\n      self.writeCmdAndData(0x3a, [0x2c])\n      self.writeCmdAndData(0x3b, [0x0b])\n      self.writeCmdAndData(0x0c, [0x8b,0x9c,0x96,0x0f])\n\n\n\n\n      \n\n  def _writeDisRam(self, sizeX, sizeY):\n    if sizeX % 8 != 0:\n      sizeX = sizeX + (8 - sizeX % 8)\n    sizeX = sizeX // 8\n    \n    self.writeCmdAndData(0x24, self._displayBuffer[0: sizeX * sizeY])\n\n\n\n  def _updateDis(self, mode):\n    if mode == self.FULL:\n     self.writeCmdAndData(0x22, [0xc7])\n    elif mode == self.PART:\n     self.writeCmdAndData(0x22, [0xc7])\n    else:\n      return\n    self.writeCmdAndData(0x20, [])\n  \n\n  def _waitBusyExit(self):\n    temp = 0\n    while self.readBusy() != False:\n      time.sleep(0.01)\n      temp = temp + 1\n      if (temp % 200) == 0:\n        print(\"waitBusyExit\")\n\n  def _powerOn(self):\n    self.writeCmdAndData(0x22, [0xC0])\n    self.writeCmdAndData(0x20, [])\n\n  def _powerOff(self):\n    self.writeCmdAndData(0x10, [0x01])\n    time.sleep(0.1)\n\n  def _disPart(self, xStart, xEnd, yStart, yEnd):\n    self._setRamData(xStart // 8, xEnd // 8, yEnd % 256, yEnd // 256, yStart % 256, yStart // 256)\n    self._setRamPointer(xStart // 8, yEnd % 256, yEnd // 256)\n    self._writeDisRam(xEnd - xStart, yEnd - yStart + 1)\n    self._updateDis(self.PART)\n\n  def flush(self, mode):\n    if mode != self.FULL and mode != self.PART:\n      return\n    self._init(mode)\n    self._initLut(mode)\n    self._powerOn()\n    if mode == self.PART:\n      self._disPart(0, self.XDOT - 1, 0, self.YDOT - 1)\n    else:\n      self._setRamPointer(0x00, (self.YDOT - 1) % 256, (self.YDOT - 1) // 256)\n      self._writeDisRam(self.XDOT, self.YDOT)\n      self._updateDis(self.FULL)\n   \n  def startDrawBitmapFile(self, x, y):\n    self._bitmapFileStartX = x\n    self._bitmapFileStartY = y\n\n  def bitmapFileHelper(self, buf):\n    for i in range(len(buf) // 3):\n      addr = i * 3\n      if buf[addr] == 0x00 and buf[addr + 1] == 0x00 and buf[addr + 2] == 0x00:\n        self.pixel(self._bitmapFileStartX, self._bitmapFileStartY, self.BLACK)\n      else:\n        self.pixel(self._bitmapFileStartX, self._bitmapFileStartY, self.WHITE)\n      self._bitmapFileStartX += 1\n  \n  def endDrawBitmapFile(self):\n    self.flush(self.PART)\n\nclass DFRobot_Epaper_SPI(DFRobot_Epaper):\n\n  def __init__(self, bus, dev, cs, cd, busy):\n    DFRobot_Epaper.__init__(self)\n    self._spi = SPI(bus, dev)\n    self._cs = GPIO(cs, GPIO.OUT)\n    self._cd = GPIO(cd, GPIO.OUT)\n    self._busy = GPIO(busy, GPIO.IN)\n  \n  def writeCmdAndData(self, cmd, data = []):\n    self._waitBusyExit()\n    self._cs.setOut(GPIO.LOW)\n    self._cd.setOut(GPIO.LOW)\n    self._spi.transfer([cmd])\n    self._cd.setOut(GPIO.HIGH)\n    self._spi.transfer(data)\n    self._cs.setOut(GPIO.HIGH)\n\n  def readBusy(self):\n    return self._busy.read()\n\n  def setBusyCB(self, cb):\n    self._busy.setInterrupt(self._busyExitEdge, cb)\n  def __del__(self):\n    RPIGPIO.cleanup()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/display_extension/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/display_extension/fonts_6_8.py",
    "content": "fonts = {  # left to right, msb to bottom, lsb to top\n  \" \": [0x00,0x00,0x00,0x00,0x00,0x00], \n  \"!\": [0x00,0x00,0x5F,0x00,0x00,0x00], \n  \"\\\"\": [0x00,0x07,0x00,0x07,0x00,0x00], \n  \"#\": [0x14,0x7F,0x14,0x7F,0x14,0x00], \n  \"$\": [0x24,0x2A,0x7F,0x2A,0x12,0x00], \n  \"%\": [0x23,0x13,0x08,0x64,0x62,0x00], \n  \"&\": [0x36,0x49,0x56,0x20,0x50,0x00], \n  \"'\": [0x00,0x08,0x07,0x03,0x00,0x00], \n  \"(\": [0x00,0x1C,0x22,0x41,0x00,0x00], \n  \")\": [0x00,0x41,0x22,0x1C,0x00,0x00], \n  \"*\": [0x24,0x18,0x7E,0x18,0x24,0x00], \n  \"+\": [0x08,0x08,0x3E,0x08,0x08,0x00], \n  \",\": [0x00,0x80,0x70,0x30,0x00,0x00], \n  \"-\": [0x08,0x08,0x08,0x08,0x08,0x00], \n  \".\": [0x00,0x00,0x60,0x60,0x00,0x00], \n  \"/\": [0x20,0x10,0x08,0x04,0x02,0x00], \n  \"0\": [0x3E,0x41,0x49,0x41,0x3E,0x00], \n  \"1\": [0x00,0x42,0x7F,0x40,0x00,0x00], \n  \"2\": [0x72,0x49,0x49,0x49,0x46,0x00], \n  \"3\": [0x21,0x41,0x49,0x4D,0x32,0x00], \n  \"4\": [0x18,0x14,0x12,0x7F,0x10,0x00], \n  \"5\": [0x27,0x45,0x45,0x45,0x38,0x00], \n  \"6\": [0x3C,0x4A,0x49,0x49,0x31,0x00], \n  \"7\": [0x41,0x21,0x11,0x09,0x07,0x00], \n  \"8\": [0x36,0x49,0x49,0x49,0x36,0x00], \n  \"9\": [0x46,0x49,0x49,0x29,0x16,0x00], \n  \":\": [0x00,0x00,0x14,0x00,0x00,0x00], \n  \";\": [0x00,0x40,0x34,0x00,0x00,0x00], \n  \"<\": [0x00,0x08,0x14,0x22,0x41,0x00], \n  \"=\": [0x14,0x14,0x14,0x14,0x14,0x00], \n  \">\": [0x00,0x41,0x22,0x14,0x08,0x00], \n  \"?\": [0x02,0x01,0x59,0x09,0x06,0x00], \n  \"@\": [0x3E,0x41,0x5D,0x59,0x4E,0x00], \n  \"A\": [0x7C,0x12,0x11,0x12,0x7C,0x00], \n  \"B\": [0x7F,0x49,0x49,0x49,0x36,0x00], \n  \"C\": [0x3E,0x41,0x41,0x41,0x22,0x00], \n  \"D\": [0x7F,0x41,0x41,0x41,0x3E,0x00], \n  \"E\": [0x7F,0x49,0x49,0x49,0x41,0x00], \n  \"F\": [0x7F,0x09,0x09,0x09,0x01,0x00], \n  \"G\": [0x3E,0x41,0x41,0x51,0x73,0x00], \n  \"H\": [0x7F,0x08,0x08,0x08,0x7F,0x00], \n  \"I\": [0x00,0x41,0x7F,0x41,0x00,0x00], \n  \"J\": [0x20,0x40,0x41,0x3F,0x01,0x00], \n  \"K\": [0x7F,0x08,0x14,0x22,0x41,0x00], \n  \"L\": [0x7F,0x40,0x40,0x40,0x40,0x00], \n  \"M\": [0x7F,0x02,0x1C,0x02,0x7F,0x00], \n  \"N\": [0x7F,0x04,0x08,0x10,0x7F,0x00], \n  \"O\": [0x3E,0x41,0x41,0x41,0x3E,0x00], \n  \"P\": [0x7F,0x09,0x09,0x09,0x06,0x00], \n  \"Q\": [0x3E,0x41,0x51,0x21,0x5E,0x00], \n  \"R\": [0x7F,0x09,0x19,0x29,0x46,0x00], \n  \"S\": [0x26,0x49,0x49,0x49,0x32,0x00], \n  \"T\": [0x03,0x01,0x7F,0x01,0x03,0x00], \n  \"U\": [0x3F,0x40,0x40,0x40,0x3F,0x00], \n  \"V\": [0x1F,0x20,0x40,0x20,0x1F,0x00], \n  \"W\": [0x3F,0x40,0x38,0x40,0x3F,0x00], \n  \"X\": [0x63,0x14,0x08,0x14,0x63,0x00], \n  \"Y\": [0x03,0x04,0x78,0x04,0x03,0x00], \n  \"Z\": [0x61,0x59,0x49,0x4D,0x43,0x00], \n  \"[\": [0x00,0x7F,0x41,0x41,0x41,0x00], \n  \"\\\\\": [0x02,0x04,0x08,0x10,0x20,0x00], \n  \"]\": [0x00,0x41,0x41,0x41,0x7f,0x00], \n  \"^\": [0x04,0x02,0x01,0x02,0x04,0x00], \n  \"_\": [0x40,0x40,0x40,0x40,0x46,0x00], \n  \"'\": [0x00,0x03,0x07,0x08,0x00,0x00], \n  \"a\": [0x20,0x54,0x54,0x78,0x40,0x00], \n  \"b\": [0x7F,0x28,0x44,0x44,0x38,0x00], \n  \"c\": [0x38,0x44,0x44,0x44,0x28,0x00], \n  \"d\": [0x38,0x44,0x44,0x28,0x7F,0x00], \n  \"e\": [0x38,0x54,0x54,0x54,0x18,0x00], \n  \"f\": [0x00,0x08,0x7E,0x09,0x02,0x00], \n  \"g\": [0x38,0xA4,0xA4,0x9C,0x78,0x00], \n  \"h\": [0x7F,0x08,0x04,0x04,0x78,0x00], \n  \"i\": [0x00,0x44,0x7D,0x40,0x00,0x00], \n  \"j\": [0x20,0x40,0x40,0x3D,0x00,0x00], \n  \"k\": [0x7F,0x10,0x28,0x44,0x00,0x00], \n  \"l\": [0x00,0x41,0x7F,0x40,0x00,0x00], \n  \"m\": [0x7C,0x04,0x78,0x04,0x78,0x00], \n  \"n\": [0x7C,0x08,0x04,0x04,0x78,0x00], \n  \"o\": [0x38,0x44,0x44,0x44,0x38,0x00], \n  \"p\": [0xFC,0x18,0x24,0x24,0x18,0x00], \n  \"q\": [0x18,0x24,0x24,0x18,0xFC,0x00], \n  \"r\": [0x7C,0x08,0x04,0x04,0x08,0x00], \n  \"s\": [0x48,0x54,0x54,0x54,0x24,0x00], \n  \"t\": [0x04,0x04,0x3F,0x44,0x24,0x00], \n  \"u\": [0x3C,0x40,0x40,0x20,0x7C,0x00], \n  \"v\": [0x1C,0x20,0x40,0x20,0x1C,0x00], \n  \"w\": [0x3C,0x40,0x20,0x40,0x3C,0x00], \n  \"x\": [0x44,0x28,0x10,0x28,0x44,0x00], \n  \"y\": [0x4C,0x90,0x90,0x90,0x7C,0x00], \n  \"z\": [0x44,0x64,0x54,0x4C,0x44,0x00], \n  \"{\": [0x00,0x08,0x36,0x41,0x00,0x00], \n  \"|\": [0x00,0x00,0x77,0x00,0x00,0x00], \n  \"}\": [0x00,0x41,0x36,0x08,0x00,0x00], \n  \"~\": [0x02,0x01,0x02,0x04,0x02,0x00]\n}\n\nwidth = 6\nheight = 8\nfmt = \"LRMBLT\"\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/display_extension/fonts_8_16.py",
    "content": "fonts = { # top to bottom, msb left, lsb right\n  \" \": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], \n  \"!\": [0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00], \n  \"\\\"\": [0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],\n  \"#\": [0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00], \n  \"$\": [0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00], \n  \"%\": [0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00], \n  \"&\": [0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00], \n  \"'\": [0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], \n  \"(\": [0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00], \n  \")\": [0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00], \n  \"*\": [0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00], \n  \"+\": [0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00], \n  \",\": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00], \n  \"-\": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], \n  \".\": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00], \n  \"/\": [0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00], \n  \"0\": [0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"1\": [0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00], \n  \"2\": [0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00], \n  \"3\": [0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"4\": [0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00], \n  \"5\": [0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00], \n  \"6\": [0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"7\": [0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00], \n  \"8\": [0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"9\": [0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00], \n  \":\": [0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00], \n  \";\": [0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00], \n  \"<\": [0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00], \n  \"=\": [0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00], \n  \">\": [0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00], \n  \"?\": [0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00], \n  \"@\": [0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00], \n  \"A\": [0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00], \n  \"B\": [0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00], \n  \"C\": [0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00], \n  \"D\": [0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00], \n  \"E\": [0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00], \n  \"F\": [0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00], \n  \"G\": [0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00], \n  \"H\": [0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00], \n  \"I\": [0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00], \n  \"J\": [0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00], \n  \"K\": [0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00], \n  \"L\": [0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00], \n  \"M\": [0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00], \n  \"N\": [0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00], \n  \"O\": [0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00], \n  \"P\": [0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00], \n  \"Q\": [0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00], \n  \"R\": [0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00], \n  \"S\": [0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"T\": [0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00], \n  \"U\": [0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"V\": [0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00], \n  \"W\": [0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00], \n  \"X\": [0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00], \n  \"Y\": [0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00], \n  \"Z\": [0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00], \n  \"[\": [0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00], \n  \"\\\\\": [0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00],\n  \"]\": [0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00], \n  \"^\": [0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], \n  \"_\": [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00], \n  \"'\": [0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], \n  \"a\": [0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00], \n  \"b\": [0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00], \n  \"c\": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"d\": [0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00], \n  \"e\": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"f\": [0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00], \n  \"g\": [0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00], \n  \"h\": [0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00], \n  \"i\": [0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00], \n  \"j\": [0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00], \n  \"k\": [0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00], \n  \"l\": [0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00], \n  \"m\": [0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00], \n  \"n\": [0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00], \n  \"o\": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"p\": [0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00], \n  \"q\": [0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00], \n  \"r\": [0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00], \n  \"s\": [0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00], \n  \"t\": [0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00], \n  \"u\": [0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00], \n  \"v\": [0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00], \n  \"w\": [0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00], \n  \"x\": [0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00], \n  \"y\": [0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00], \n  \"z\": [0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00], \n  \"{\": [0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00], \n  \"|\": [0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00], \n  \"}\": [0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00], \n  \"~\": [0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]\n}\n\nwidth = 8\nheight = 16\nfmt = \"TBMLLR\"\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/display_extension/freetype_helper.py",
    "content": "# -*- coding:utf-8 -*-\n\n'''\ndepends: freetype-py\n'''\n\nimport freetype\nimport math\n#import sys\n\n#reload(sys)\n#sys.setdefaultencoding(\"utf-8\")\nimport importlib,sys\n\n#importlib.reload(sys)\nclass Freetype_Helper:\n\n  def __init__(self, filePath):\n    self._face = freetype.Face(filePath)\n    self._width = 0\n    self._height = 0\n    self._fade = 96\n\n  def setFmt(self, width, height):\n    self._width = int(width)\n    self._height = int(height)\n    self._face.set_pixel_sizes(width, height)\n  \n  def setDisLowerLimite(self, limite):\n    self._fade = limite\n\n  def getOne(self, ch):\n    self._face.load_char(ch)\n    bitmap = self._face.glyph.bitmap\n    originY = self._face.glyph.bitmap_top\n    width = bitmap.width\n    height = bitmap.rows\n    buffer = bitmap.buffer\n    rslt = []\n\n    # width = 4\n    # height = 4\n    # buffer = [0xff] * width * height\n\n    if height > self._height:\n      buffer = buffer[0: width * self._height]\n      height = self._height\n    if width > self._width:\n      for i in range(height):\n        rslt += buffer[i * width: i * width + self._width]\n      width = self._width\n      buffer = rslt\n      rslt = []\n    if (ord(ch) >= ord(\" \") and ord(ch) <= ord(\"~\")) or width <= (self._width // 2):\n      rslt = [0] * (((self._width - 1) // 16 + 1) * self._height + 1)\n      left = (self._width // 2 - width) // 2\n      lineDataLen = (self._width - 1) // 16 + 1\n    else:\n      rslt = [0] * (((self._width - 1) // 8 + 1) * self._height + 1)\n      left = (self._width - width) // 2\n      lineDataLen = (self._width - 1) // 8 + 1\n    if left < 0:\n      left = 0\n    # top = (self._height - height) * lineDataLen // 2\n    top = ((self._height * 8 + 5) // 10 - originY) * lineDataLen\n    if top < 0:\n      top = 0\n    for i in range(height):\n      for j in range(width):\n        if buffer[i * width + j] > self._fade:\n          try:\n            rslt[i * lineDataLen + (j + left) // 8 + top] |= 0x80 >> ((j + left) % 8)\n          except:\n            print(\"freetype_helper getOne err: width: %d, height: %d, top: %d, left: %d, rslt_len: %d, originY: %d\" %(width, height, top, left, len(rslt), originY))\n            raise(\"err\")\n          # rslt[i * lineDataLen + (j + left) // 8 + top] |= 0x80 >> ((j + left) % 8)\n    if (ord(ch) >= ord(\" \") and ord(ch) <= ord(\"~\")) or width < (self._width // 2):\n      return (rslt, self._width // 2, self._height, \"TBMLLR\")\n    else:\n      return (rslt, self._width, self._height, \"TBMLLR\")\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/display_extension/readme.md",
    "content": "wqydkzh.ttf = 文泉驿等宽正黑.ttf GPL2 license </br>\nzkklt.ttf = 站酷快乐体.ttf Chinese open source fonts file, use with freetype_helper.py"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/gpio.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport time\nimport RPi.GPIO as RPIGPIO\n\nRPIGPIO.setmode(RPIGPIO.BCM)\nRPIGPIO.setwarnings(False)\n\nclass GPIO:\n\n  HIGH = RPIGPIO.HIGH\n  LOW = RPIGPIO.LOW\n\n  OUT = RPIGPIO.OUT\n  IN = RPIGPIO.IN\n\n  RISING = RPIGPIO.RISING\n  FALLING = RPIGPIO.FALLING\n  BOTH = RPIGPIO.BOTH\n\n  def __init__(self, pin, mode, defaultOut = HIGH):\n    self._pin = pin\n    self._fInt = None\n    self._intDone = True\n    self._intMode = None\n    if mode == self.OUT:\n      RPIGPIO.setup(pin, mode)\n      if defaultOut == self.HIGH:\n        RPIGPIO.output(pin, defaultOut)\n      else:\n        RPIGPIO.output(pin, self.LOW)\n    else:\n      RPIGPIO.setup(pin, self.IN, pull_up_down = RPIGPIO.PUD_UP)\n\n  def setOut(self, level):\n    if level:\n      RPIGPIO.output(self._pin, self.HIGH)\n    else:\n      RPIGPIO.output(self._pin, self.LOW)\n\n  def _intCB(self, status):\n    if self._intDone:\n      self._intDone = False\n      time.sleep(0.02)\n      if self._intMode == self.BOTH:\n        self._fInt()\n      elif self._intMode == self.RISING and self.read() == self.HIGH:\n        self._fInt()\n      elif self._intMode == self.FALLING and self.read() == self.LOW:\n        self._fInt()\n      self._intDone = True\n\n  def setInterrupt(self, mode, cb):\n    if mode != self.RISING and mode != self.FALLING and mode != self.BOTH:\n      return\n    self._intMode = mode\n    RPIGPIO.add_event_detect(self._pin, mode, self._intCB)\n    self._fInt = cb\n\n  def read(self):\n    return RPIGPIO.input(self._pin)\n  \n  def cleanup(self):\n    RPIGPIO.cleanup()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/i2c.py",
    "content": "# -*- coding:utf-8 -*-\n\n'''\nchange i2c frequency on raspberry:\n  1. edit /etc/modprobe.d\n  2. add line: \n    options i2c_bcm2708 baudrate=400000\n'''\n\nimport smbus\n\nclass I2C:\n\n  def __init__(self, port):\n    self._bus = smbus.SMBus(port)\n\n  def writeBytes(self, addr, reg, buf):\n    self._bus.write_block_data(addr, reg, buf)\n  \n  def readBytes(self, addr, reg, length):\n    return self._bus.read_block_data(addr, reg, length)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/dfrobot/v2/spi.py",
    "content": "# -*- coding:utf-8 -*-\n\nimport spidev\n\nclass SPI:\n\n  MODE_1 = 1\n  MODE_2 = 2\n  MODE_3 = 3\n  MODE_4 = 4\n\n  def __init__(self, bus, dev, speed = 3900000, mode = MODE_4):\n    self._bus = spidev.SpiDev()\n    self._bus.open(0, 0)\n    self._bus.no_cs = True\n    self._bus.max_speed_hz = speed\n\n  def transfer(self, buf):\n    if len(buf):\n      return self._bus.xfer(buf)\n    return []\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/fb/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/fb/fb.py",
    "content": "FBIOGET_VSCREENINFO=0x4600\nFBIOPUT_VSCREENINFO=0x4601\nFBIOGET_FSCREENINFO=0x4602\nFBIOGETCMAP=0x4604\nFBIOPUTCMAP=0x4605\nFBIOPAN_DISPLAY=0x4606\n\nFBIOGET_CON2FBMAP=0x460F\nFBIOPUT_CON2FBMAP=0x4610\nFBIOBLANK=0x4611\nFBIO_ALLOC=0x4613\nFBIO_FREE=0x4614\nFBIOGET_GLYPH=0x4615\nFBIOGET_HWCINFO=0x4616\nFBIOPUT_MODEINFO=0x4617\nFBIOGET_DISPINFO=0x4618\n\nfrom mmap import mmap\nfrom fcntl import ioctl\nimport struct\n\nmm = None\nbpp, w, h = 0, 0, 0 # framebuffer bpp and size\nbytepp = 0\nvx, vy, vw, vh = 0, 0, 0, 0 #virtual window offset and size\nvi, fi = None, None\n_fb_cmap = 'IIPPPP' # start, len, r, g, b, a\nRGB = False\n_verbose = False\nmsize_kb = 0\n\ndef report_fb(i=0, layer=0):\n  with open('/dev/fb'+str(i), 'r+b')as f:\n    vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))\n    vi = list(struct.unpack('I'*40, vi))\n    ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH'\n    fic = struct.calcsize(ffm)\n    fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))\n\ndef ready_fb(_bpp=None, i=0, layer=0, _win=None):\n  global mm, bpp, w, h, vi, fi, RGB, msize_kb, vx, vy, vw, vh, bytepp\n  if mm and bpp == _bpp: return mm, w, h, bpp\n  with open('/dev/fb'+str(i), 'r+b')as f:\n    vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))\n    vi = list(struct.unpack('I'*40, vi))\n    bpp = vi[6]\n    bytepp = bpp//8\n    if _bpp:\n      vi[6] = _bpp # 24 bit = BGR 888 mode\n      try:\n        vi = ioctl(f, FBIOPUT_VSCREENINFO, struct.pack('I'*40, *vi)) # fb_var_screeninfo\n        vi = struct.unpack('I'*40,vi)\n        bpp = vi[6]\n        bytepp = bpp//8\n      except:\n        pass\n    \n    if vi[8] == 0 : RGB = True\n    \n    ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH'\n    fic = struct.calcsize(ffm)\n    fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))\n    msize = fi[17] # = w*h*bpp//8\n    ll, start = fi[-7:-5]\n    w, h = ll//bytepp, vi[1] # when screen is vertical, width becomes wrong. ll//3 is more accurate at such time.\n    if _win and len(_win)==4: # virtual window settings\n      vx, vy, vw, vh = _win\n      if vw == 'w': vw = w\n      if vh == 'h': vh = h\n      vx, vy, vw, vh = map(int, (vx, vy, vw, vh))\n      if vx>=w: vx = 0\n      if vy>=h: vy = 0\n      if vx>w: vw = w - vx\n      else: vw -= vx\n      if vy>h: vh = h - vy\n      else: vh -= vy\n    else:\n      vx, vy, vw, vh = 0,0,w,h\n    msize_kb = vw*vh*bytepp//1024 # more accurate FB memory size in kb\n\n    mm = mmap(f.fileno(), msize, offset=start)\n    return mm, w, h, bpp#ll//(bpp//8), h\n\ndef fill_scr(r,g,b):\n  if bpp == 32:\n    seed = struct.pack('BBBB', b, g, r, 255)\n  elif bpp == 24:\n    seed = struct.pack('BBB', b, g, r)\n  elif bpp == 16:\n    seed = struct.pack('H', r>>3<<11 | g>>2<<5 | b>>3)\n  mm.seek(0)\n  show_img(seed * vw * vh)\n\ndef black_scr():\n  fill_scr(0,0,0)\n\ndef white_scr():\n  fill_scr(255,255,255)\n\ndef mmseekto(x,y):\n  mm.seek((x + y*w) * bytepp)\n\ndef dot(x, y, r, g, b):\n  mmseekto(x,y)\n  mm.write(struct.pack('BBB',*((r,g,b) if RGB else (b,g,r))))\n\ndef get_pixel(x,y):\n  mmseekto(x,y)\n  return mm.read(bytepp)\n\ndef _888_to_565(bt):\n  b = b''\n  for i in range(0, len(bt),3):\n    b += int.to_bytes(bt[i]>>3<<11|bt[i+1]>>2<<5|bt[i+2]>>3, 2, 'little')\n  return b\n\ndef numpy_888_565(bt):\n  import numpy as np\n  arr = np.fromstring(bt, dtype=np.uint32)\n  return (((0xF80000 & arr)>>8)|((0xFC00 & arr)>>5)|((0xF8 & arr)>>3)).astype(np.uint16).tostring()\n\ndef show_img(img):\n  if not type(img) is bytes:\n    if not RGB:\n      if bpp == 24: # for RPI\n        img = img.tobytes('raw', 'BGR')\n      else:\n        img = img.convert('RGBA').tobytes('raw', 'BGRA')\n        if bpp == 16:\n          img = numpy_888_565(img)\n    else:\n      if bpp == 24:\n        img = img.tobytes()\n      else:\n        img = img.convert('RGBA').tobytes()\n        if bpp == 16:\n          img = numpy_888_565(img)\n  from io import BytesIO\n  b = BytesIO(img)\n  s = vw*bytepp\n  for y in range(vh): # virtual window drawing\n    mmseekto(vx,vy+y)\n    mm.write(b.read(s))\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/inkyphat/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/inkyphat/inkyfast.py",
    "content": "from inky.inky import Inky, CS0_PIN, DC_PIN, RESET_PIN, BUSY_PIN\n\n\nclass InkyFast(Inky):\n\n    def __init__(self, resolution=(400, 300), colour='black', cs_pin=CS0_PIN, dc_pin=DC_PIN, reset_pin=RESET_PIN,\n                 busy_pin=BUSY_PIN, h_flip=False, v_flip=False):\n        super(InkyFast, self).__init__(resolution, colour, cs_pin, dc_pin, reset_pin, busy_pin, h_flip, v_flip)\n\n        self._luts['black'] = [\n                0b01001000, 0b10100000, 0b00010000, 0b00010000, 0b00010011, 0b00000000, 0b00000000,\n                0b01001000, 0b10100000, 0b10000000, 0b00000000, 0b00000011, 0b00000000, 0b00000000,\n                0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,\n                0b01001000, 0b10100101, 0b00000000, 0b10111011, 0b00000000, 0b00000000, 0b00000000,\n                0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,\n                # The following timings have been reduced to avoid the fade to black\n                0x00, 0x00, 0x00, 0x00, 0x00,\n                0x10, 0x04, 0x04, 0x04, 0x04,\n                0x04, 0x08, 0x08, 0x10, 0x10,\n                0x00, 0x00, 0x00, 0x00, 0x00,\n                0x00, 0x00, 0x00, 0x00, 0x00,\n                0x00, 0x00, 0x00, 0x00, 0x00,\n                0x00, 0x00, 0x00, 0x00, 0x00,\n            ]"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/inkyphat/inkyphatfast.py",
    "content": "\"\"\"Inky pHAT e-Ink Display Driver.\"\"\"\nfrom . import inkyfast\n\n\nclass InkyPHATFast(inkyfast.InkyFast):\n    \"\"\"Inky wHAT e-Ink Display Driver.\"\"\"\n\n    WIDTH = 212\n    HEIGHT = 104\n\n    WHITE = 0\n    BLACK = 1\n    RED = 2\n    YELLOW = 2\n\n    def __init__(self, colour):\n        \"\"\"Initialise an Inky pHAT Display.\n\n        :param colour: one of red, black or yellow, default: black\n\n        \"\"\"\n        inkyfast.InkyFast.__init__(\n            self,\n            resolution=(self.WIDTH, self.HEIGHT),\n            colour=colour,\n            h_flip=False,\n            v_flip=False)"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/papirus/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/papirus/epd.py",
    "content": "#qCopyright 2013-2015 Pervasive Displays, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at:\n#\n#   http:#www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either\n# express or implied.  See the License for the specific language\n# governing permissions and limitations under the License.\n\n\nfrom PIL import Image\nfrom PIL import ImageOps\nfrom pwnagotchi.ui.hw.libs.papirus.lm75b import LM75B\nimport re\nimport os\nimport sys\n\nif sys.version_info < (3,):\n    def b(x):\n        return x\nelse:\n    def b(x):\n        return x.encode('ISO-8859-1')\n\nclass EPDError(Exception):\n    def __init__(self, value):\n        self.value = value\n\n    def __str__(self):\n        return repr(self.value)\n\n\nclass EPD(object):\n\n    \"\"\"EPD E-Ink interface\n\nto use:\n  from EPD import EPD\n\n  epd = EPD([path='/path/to/epd'], [auto=boolean], [rotation = 0|90|180|270])\n\n  image = Image.new('1', epd.size, 0)\n  # draw on image\n  epd.clear()         # clear the panel\n  epd.display(image)  # transfer image data\n  epd.update()        # refresh the panel image - not needed if auto=true\n\"\"\"\n\n\n    PANEL_RE = re.compile('^([A-Za-z]+)\\s+(\\d+\\.\\d+)\\s+(\\d+)x(\\d+)\\s+COG\\s+(\\d+)\\s+FILM\\s+(\\d+)\\s*$', flags=0)\n\n    def __init__(self, *args, **kwargs):\n        self._epd_path = '/dev/epd'\n        self._width = 200\n        self._height = 96\n        self._panel = 'EPD 2.0'\n        self._cog = 0\n        self._film = 0\n        self._auto = False\n        self._lm75b = LM75B()\n        self._rotation = 0\n        self._uselm75b = True\n\n        if len(args) > 0:\n            self._epd_path = args[0]\n        elif 'epd' in kwargs:\n            self._epd_path = kwargs['epd']\n\n        if ('auto' in kwargs) and kwargs['auto']:\n            self._auto = True\n        if ('rotation' in kwargs):\n            rot = kwargs['rotation']\n            if rot in (0, 90, 180, 270):\n                self._rotation = rot\n            else:\n                raise EPDError('rotation can only be 0, 90, 180 or 270')\n\n        with open(os.path.join(self._epd_path, 'version')) as f:\n            self._version = f.readline().rstrip('\\n')\n\n        with open(os.path.join(self._epd_path, 'panel')) as f:\n            line = f.readline().rstrip('\\n')\n            m = self.PANEL_RE.match(line)\n            if m is None:\n                raise EPDError('invalid panel string')\n            self._panel = m.group(1) + ' ' + m.group(2)\n            self._width = int(m.group(3))\n            self._height = int(m.group(4))\n            self._cog = int(m.group(5))\n            self._film = int(m.group(6))\n\n        if self._width < 1 or self._height < 1:\n            raise EPDError('invalid panel geometry')\n        if self._rotation in (90, 270):\n            self._width, self._height = self._height, self._width\n\n    @property\n    def size(self):\n        return (self._width, self._height)\n\n    @property\n    def width(self):\n        return self._width\n\n    @property\n    def height(self):\n        return self._height\n\n    @property\n    def panel(self):\n        return self._panel\n\n    @property\n    def version(self):\n        return self._version\n\n    @property\n    def cog(self):\n        return self._cog\n\n    @property\n    def film(self):\n        return self._film\n\n    @property\n    def auto(self):\n        return self._auto\n\n    @auto.setter\n    def auto(self, flag):\n        if flag:\n            self._auto = True\n        else:\n            self._auto = False\n\n    @property\n    def rotation(self):\n        return self._rotation\n\n    @rotation.setter\n    def rotation(self, rot):\n        if rot not in (0, 90, 180, 270):\n            raise EPDError('rotation can only be 0, 90, 180 or 270')\n        if abs(self._rotation - rot) == 90 or abs(self._rotation - rot) == 270:\n            self._width, self._height = self._height, self._width\n        self._rotation = rot\n\n    @property\n    def use_lm75b(self):\n        return self._uselm75b\n\n    @use_lm75b.setter\n    def use_lm75b(self, flag):\n        if flag:\n            self._uselm75b = True\n        else:\n            self._uselm75b = False\n\n    def error_status(self):\n        with open(os.path.join(self._epd_path, 'error'), 'r') as f:\n            return(f.readline().rstrip('\\n'))\n\n    def rotation_angle(self, rotation):\n        angles = { 90 : Image.ROTATE_90, 180 : Image.ROTATE_180, 270 : Image.ROTATE_270 }\n        return angles[rotation]\n\n    def display(self, image):\n\n        # attempt grayscale conversion, and then to single bit\n        # better to do this before calling this if the image is to\n        # be displayed several times\n        if image.mode != \"1\":\n            image = ImageOps.grayscale(image).convert(\"1\", dither=Image.FLOYDSTEINBERG)\n\n        if image.mode != \"1\":\n            raise EPDError('only single bit images are supported')\n\n        if image.size != self.size:\n            raise EPDError('image size mismatch')\n\n        if self._rotation != 0:\n            image = image.transpose(self.rotation_angle(self._rotation))\n\n        with open(os.path.join(self._epd_path, 'LE', 'display_inverse'), 'r+b') as f:\n            f.write(image.tobytes())\n\n        if self.auto:\n            self.update()\n\n\n    def update(self):\n        self._command('U')\n\n    def partial_update(self):\n        self._command('P')\n\n    def fast_update(self):\n        self._command('F')\n\n    def clear(self):\n        self._command('C')\n\n    def _command(self, c):\n        if self._uselm75b:\n            with open(os.path.join(self._epd_path, 'temperature'), 'wb') as f:\n                f.write(b(repr(self._lm75b.getTempC())))\n        with open(os.path.join(self._epd_path, 'command'), 'wb') as f:\n            f.write(b(c))\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/papirus/lm75b.py",
    "content": "# Minimal support for LM75b temperature sensor on the Papirus HAT / Papirus Zero\n# This module allows you to read the temperature.\n# The OS-output (Over-temperature Shutdown) connected to GPIO xx (pin 11) is not supported\n# by this module\n#\n\nfrom __future__ import (print_function, division)\n\nimport smbus\n\nLM75B_ADDRESS             = 0x48\n\nLM75B_TEMP_REGISTER       = 0\nLM75B_CONF_REGISTER       = 1\nLM75B_THYST_REGISTER      = 2\nLM75B_TOS_REGISTER        = 3\n\nLM75B_CONF_NORMAL         = 0\n\nclass LM75B(object):\n    def __init__(self, address=LM75B_ADDRESS, busnum=1):\n        self._address = address\n        self._bus = smbus.SMBus(busnum)\n        self._bus.write_byte_data(self._address, LM75B_CONF_REGISTER, LM75B_CONF_NORMAL)\n\n    def getTempCFloat(self):\n        \"\"\"Return temperature in degrees Celsius as float\"\"\"\n        raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF\n        raw = ((raw << 8) & 0xFF00) + (raw >> 8)\n        return (raw / 32.0) / 8.0\n\n    def getTempFFloat(self):\n        \"\"\"Return temperature in degrees Fahrenheit as float\"\"\"\n        return (self.getTempCFloat() * (9.0 / 5.0)) + 32.0\n\n    def getTempC(self):\n        \"\"\"Return temperature in degrees Celsius as integer, so it can be\n           used to write to /dev/epd/temperature\"\"\"\n        raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF\n        raw = ((raw << 8) & 0xFF00) + (raw >> 8)\n        return (raw + 128) // 256 # round to nearest integer\n\nif __name__ == \"__main__\":\n    sens = LM75B()\n    print(sens.getTempC(), sens.getTempFFloat())\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat/ST7789.py",
    "content": "import spidev\r\nimport RPi.GPIO as GPIO\r\nimport time\r\nimport numpy as np\r\n\r\n\r\nclass ST7789(object):\r\n    \"\"\"class for ST7789  240*240 1.3inch OLED displays.\"\"\"\r\n\r\n    def __init__(self, spi, rst=27, dc=25, bl=24):\r\n        self.width = 240\r\n        self.height = 240\r\n        # Initialize DC RST pin\r\n        self._dc = dc\r\n        self._rst = rst\r\n        self._bl = bl\r\n        GPIO.setmode(GPIO.BCM)\r\n        GPIO.setwarnings(False)\r\n        GPIO.setup(self._dc, GPIO.OUT)\r\n        GPIO.setup(self._rst, GPIO.OUT)\r\n        GPIO.setup(self._bl, GPIO.OUT)\r\n        GPIO.output(self._bl, GPIO.HIGH)\r\n        # Initialize SPI\r\n        self._spi = spi\r\n        self._spi.max_speed_hz = 40000000\r\n\r\n    \"\"\"    Write register address and data     \"\"\"\r\n\r\n    def command(self, cmd):\r\n        GPIO.output(self._dc, GPIO.LOW)\r\n        self._spi.writebytes([cmd])\r\n\r\n    def data(self, val):\r\n        GPIO.output(self._dc, GPIO.HIGH)\r\n        self._spi.writebytes([val])\r\n\r\n    def Init(self):\r\n        \"\"\"Initialize display\"\"\"\r\n        self.reset()\r\n\r\n        self.command(0x36)\r\n        self.data(0x70)  # self.data(0x00)\r\n\r\n        self.command(0x3A)\r\n        self.data(0x05)\r\n\r\n        self.command(0xB2)\r\n        self.data(0x0C)\r\n        self.data(0x0C)\r\n        self.data(0x00)\r\n        self.data(0x33)\r\n        self.data(0x33)\r\n\r\n        self.command(0xB7)\r\n        self.data(0x35)\r\n\r\n        self.command(0xBB)\r\n        self.data(0x19)\r\n\r\n        self.command(0xC0)\r\n        self.data(0x2C)\r\n\r\n        self.command(0xC2)\r\n        self.data(0x01)\r\n\r\n        self.command(0xC3)\r\n        self.data(0x12)\r\n\r\n        self.command(0xC4)\r\n        self.data(0x20)\r\n\r\n        self.command(0xC6)\r\n        self.data(0x0F)\r\n\r\n        self.command(0xD0)\r\n        self.data(0xA4)\r\n        self.data(0xA1)\r\n\r\n        self.command(0xE0)\r\n        self.data(0xD0)\r\n        self.data(0x04)\r\n        self.data(0x0D)\r\n        self.data(0x11)\r\n        self.data(0x13)\r\n        self.data(0x2B)\r\n        self.data(0x3F)\r\n        self.data(0x54)\r\n        self.data(0x4C)\r\n        self.data(0x18)\r\n        self.data(0x0D)\r\n        self.data(0x0B)\r\n        self.data(0x1F)\r\n        self.data(0x23)\r\n\r\n        self.command(0xE1)\r\n        self.data(0xD0)\r\n        self.data(0x04)\r\n        self.data(0x0C)\r\n        self.data(0x11)\r\n        self.data(0x13)\r\n        self.data(0x2C)\r\n        self.data(0x3F)\r\n        self.data(0x44)\r\n        self.data(0x51)\r\n        self.data(0x2F)\r\n        self.data(0x1F)\r\n        self.data(0x1F)\r\n        self.data(0x20)\r\n        self.data(0x23)\r\n\r\n        self.command(0x21)\r\n\r\n        self.command(0x11)\r\n\r\n        self.command(0x29)\r\n\r\n    def reset(self):\r\n        \"\"\"Reset the display\"\"\"\r\n        GPIO.output(self._rst, GPIO.HIGH)\r\n        time.sleep(0.01)\r\n        GPIO.output(self._rst, GPIO.LOW)\r\n        time.sleep(0.01)\r\n        GPIO.output(self._rst, GPIO.HIGH)\r\n        time.sleep(0.01)\r\n\r\n    def SetWindows(self, Xstart, Ystart, Xend, Yend):\r\n        # set the X coordinates\r\n        self.command(0x2A)\r\n        self.data(0x00)  # Set the horizontal starting point to the high octet\r\n        self.data(Xstart & 0xff)  # Set the horizontal starting point to the low octet\r\n        self.data(0x00)  # Set the horizontal end to the high octet\r\n        self.data((Xend - 1) & 0xff)  # Set the horizontal end to the low octet\r\n\r\n        # set the Y coordinates\r\n        self.command(0x2B)\r\n        self.data(0x00)\r\n        self.data((Ystart & 0xff))\r\n        self.data(0x00)\r\n        self.data((Yend - 1) & 0xff)\r\n\r\n        self.command(0x2C)\r\n\r\n    def ShowImage(self, Image, Xstart, Ystart):\r\n        \"\"\"Set buffer to value of Python Imaging Library image.\"\"\"\r\n        \"\"\"Write display buffer to physical display\"\"\"\r\n        imwidth, imheight = Image.size\r\n        if imwidth != self.width or imheight != self.height:\r\n            raise ValueError('Image must be same dimensions as display \\\r\n                ({0}x{1}).'.format(self.width, self.height))\r\n        img = np.asarray(Image)\r\n        pix = np.zeros((self.width, self.height, 2), dtype=np.uint8)\r\n        pix[..., [0]] = np.add(np.bitwise_and(img[..., [0]], 0xF8), np.right_shift(img[..., [1]], 5))\r\n        pix[..., [1]] = np.add(np.bitwise_and(np.left_shift(img[..., [1]], 3), 0xE0), np.right_shift(img[..., [2]], 3))\r\n        pix = pix.flatten().tolist()\r\n        self.SetWindows(0, 0, self.width, self.height)\r\n        GPIO.output(self._dc, GPIO.HIGH)\r\n        for i in range(0, len(pix), 4096):\r\n            self._spi.writebytes(pix[i:i + 4096])\r\n\r\n    def clear(self):\r\n        \"\"\"Clear contents of image buffer\"\"\"\r\n        _buffer = [0xff] * (self.width * self.height * 2)\r\n        self.SetWindows(0, 0, self.width, self.height)\r\n        GPIO.output(self._dc, GPIO.HIGH)\r\n        for i in range(0, len(_buffer), 4096):\r\n            self._spi.writebytes(_buffer[i:i + 4096])\r\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat/config.py",
    "content": "# /*****************************************************************************\n# * | File        :   config.py\n# * | Author      :   Guillaume Giraudon\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-10-18\n# * | Info        :\n# ******************************************************************************/\nimport spidev\n\n# Pin definition\nRST_PIN = 27\nDC_PIN = 25\nBL_PIN = 24\n\nDevice_SPI = 1\nDevice_I2C = 0\n\nDevice = Device_SPI\nspi = spidev.SpiDev(0, 0)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat/epd.py",
    "content": "from . import ST7789\nfrom . import config\n\n\nclass EPD(object):\n    def __init__(self):\n        self.reset_pin = config.RST_PIN\n        self.dc_pin = config.DC_PIN\n        self.width = 240\n        self.height = 240\n        self.st7789 = ST7789.ST7789(config.spi, config.RST_PIN, config.DC_PIN, config.BL_PIN)\n\n    def init(self):\n        self.st7789.Init()\n\n    def clear(self):\n        self.st7789.clear()\n\n    def display(self, image):\n        rgb_im = image.convert('RGB')\n        self.st7789.ShowImage(rgb_im, 0, 0)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat144/LCD_1in44.py",
    "content": " # -*- coding:UTF-8 -*-\n ##\n # | file      \t:\tLCD_1IN44.py\n # |\tversion\t\t:\tV2.0\n # | date\t\t:\t2018-07-16\n # | function\t:\tOn the ST7735S chip driver and clear screen, drawing lines, drawing, writing \n #\t\t\t\t\tand other functions to achieve\n #\n # Permission is hereby granted, free of charge, to any person obtaining a copy\n # of this software and associated documnetation files (the \"Software\"), to deal\n # in the Software without restriction, including without limitation the rights\n # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n # copies of the Software, and to permit persons to  whom the Software is\n # furished to do so, subject to the following conditions:\n #\n # The above copyright notice and this permission notice shall be included in\n # all copies or substantial portions of the Software.\n #\n # THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n # FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n # LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n # THE SOFTWARE.\n #\n\n\nimport RPi.GPIO as GPIO\nimport time\nimport numpy as np\nfrom . import config\n\nLCD_1IN44 = 1\nLCD_1IN8 = 0\nif LCD_1IN44 == 1:\n\tLCD_WIDTH  = 128  #LCD width\n\tLCD_HEIGHT = 128 #LCD height\n\tLCD_X = 2\n\tLCD_Y = 1\nif LCD_1IN8 == 1:\n\tLCD_WIDTH  = 160\n\tLCD_HEIGHT = 128\n\tLCD_X = 1\n\tLCD_Y = 2\n\nLCD_X_MAXPIXEL = 132  #LCD width maximum memory \nLCD_Y_MAXPIXEL = 162  #LCD height maximum memory\n\n#scanning method\nL2R_U2D = 1\nL2R_D2U = 2\nR2L_U2D = 3\nR2L_D2U = 4\nU2D_L2R = 5\nU2D_R2L = 6\nD2U_L2R = 7\nD2U_R2L = 8\nSCAN_DIR_DFT = U2D_R2L\n\n\nclass LCD:\n\tdef __init__(self):\n\t\tGPIO.setmode(GPIO.BCM)\n\t\tself.width = LCD_WIDTH\n\t\tself.height = LCD_HEIGHT\n\t\tself.LCD_Scan_Dir = SCAN_DIR_DFT\n\t\tself.LCD_X_Adjust = LCD_X\n\t\tself.LCD_Y_Adjust = LCD_Y\n\n\t\"\"\"    Hardware reset     \"\"\"\n\tdef  LCD_Reset(self):\n\t\tGPIO.output(config.LCD_RST_PIN, GPIO.HIGH)\n\t\tconfig.Driver_Delay_ms(100)\n\t\tGPIO.output(config.LCD_RST_PIN, GPIO.LOW)\n\t\tconfig.Driver_Delay_ms(100)\n\t\tGPIO.output(config.LCD_RST_PIN, GPIO.HIGH)\n\t\tconfig.Driver_Delay_ms(100)\n\n\t\"\"\"    Write register address and data     \"\"\"\n\tdef  LCD_WriteReg(self, Reg):\n\t\tGPIO.setmode(GPIO.BCM)\n\t\tGPIO.setup(config.LCD_DC_PIN, GPIO.OUT)\n\t\tGPIO.output(config.LCD_DC_PIN, GPIO.LOW)\n\t\tconfig.SPI_Write_Byte([Reg])\n\n\tdef LCD_WriteData_8bit(self, Data):\n\t\tGPIO.output(config.LCD_DC_PIN, GPIO.HIGH)\n\t\tconfig.SPI_Write_Byte([Data])\n\n\tdef LCD_WriteData_NLen16Bit(self, Data, DataLen):\n\t\tGPIO.output(config.LCD_DC_PIN, GPIO.HIGH)\n\t\tfor i in range(0, DataLen):\n\t\t\tconfig.SPI_Write_Byte([Data >> 8])\n\t\t\tconfig.SPI_Write_Byte([Data & 0xff])\n\t\t\n\t\"\"\"    Common register initialization    \"\"\"\n\tdef LCD_InitReg(self):\n\t\t#ST7735R Frame Rate\n\t\tself.LCD_WriteReg(0xB1)\n\t\tself.LCD_WriteData_8bit(0x01)\n\t\tself.LCD_WriteData_8bit(0x2C)\n\t\tself.LCD_WriteData_8bit(0x2D)\n\n\t\tself.LCD_WriteReg(0xB2)\n\t\tself.LCD_WriteData_8bit(0x01)\n\t\tself.LCD_WriteData_8bit(0x2C)\n\t\tself.LCD_WriteData_8bit(0x2D)\n\n\t\tself.LCD_WriteReg(0xB3)\n\t\tself.LCD_WriteData_8bit(0x01)\n\t\tself.LCD_WriteData_8bit(0x2C)\n\t\tself.LCD_WriteData_8bit(0x2D)\n\t\tself.LCD_WriteData_8bit(0x01)\n\t\tself.LCD_WriteData_8bit(0x2C)\n\t\tself.LCD_WriteData_8bit(0x2D)\n\t\t\n\t\t#Column inversion \n\t\tself.LCD_WriteReg(0xB4)\n\t\tself.LCD_WriteData_8bit(0x07)\n\t\t\n\t\t#ST7735R Power Sequence\n\t\tself.LCD_WriteReg(0xC0)\n\t\tself.LCD_WriteData_8bit(0xA2)\n\t\tself.LCD_WriteData_8bit(0x02)\n\t\tself.LCD_WriteData_8bit(0x84)\n\t\tself.LCD_WriteReg(0xC1)\n\t\tself.LCD_WriteData_8bit(0xC5)\n\n\t\tself.LCD_WriteReg(0xC2)\n\t\tself.LCD_WriteData_8bit(0x0A)\n\t\tself.LCD_WriteData_8bit(0x00)\n\n\t\tself.LCD_WriteReg(0xC3)\n\t\tself.LCD_WriteData_8bit(0x8A)\n\t\tself.LCD_WriteData_8bit(0x2A)\n\t\tself.LCD_WriteReg(0xC4)\n\t\tself.LCD_WriteData_8bit(0x8A)\n\t\tself.LCD_WriteData_8bit(0xEE)\n\t\t\n\t\tself.LCD_WriteReg(0xC5)#VCOM \n\t\tself.LCD_WriteData_8bit(0x0E)\n\t\t\n\t\t#ST7735R Gamma Sequence\n\t\tself.LCD_WriteReg(0xe0)\n\t\tself.LCD_WriteData_8bit(0x0f)\n\t\tself.LCD_WriteData_8bit(0x1a)\n\t\tself.LCD_WriteData_8bit(0x0f)\n\t\tself.LCD_WriteData_8bit(0x18)\n\t\tself.LCD_WriteData_8bit(0x2f)\n\t\tself.LCD_WriteData_8bit(0x28)\n\t\tself.LCD_WriteData_8bit(0x20)\n\t\tself.LCD_WriteData_8bit(0x22)\n\t\tself.LCD_WriteData_8bit(0x1f)\n\t\tself.LCD_WriteData_8bit(0x1b)\n\t\tself.LCD_WriteData_8bit(0x23)\n\t\tself.LCD_WriteData_8bit(0x37)\n\t\tself.LCD_WriteData_8bit(0x00)\n\t\tself.LCD_WriteData_8bit(0x07)\n\t\tself.LCD_WriteData_8bit(0x02)\n\t\tself.LCD_WriteData_8bit(0x10)\n\n\t\tself.LCD_WriteReg(0xe1)\n\t\tself.LCD_WriteData_8bit(0x0f)\n\t\tself.LCD_WriteData_8bit(0x1b)\n\t\tself.LCD_WriteData_8bit(0x0f)\n\t\tself.LCD_WriteData_8bit(0x17)\n\t\tself.LCD_WriteData_8bit(0x33)\n\t\tself.LCD_WriteData_8bit(0x2c)\n\t\tself.LCD_WriteData_8bit(0x29)\n\t\tself.LCD_WriteData_8bit(0x2e)\n\t\tself.LCD_WriteData_8bit(0x30)\n\t\tself.LCD_WriteData_8bit(0x30)\n\t\tself.LCD_WriteData_8bit(0x39)\n\t\tself.LCD_WriteData_8bit(0x3f)\n\t\tself.LCD_WriteData_8bit(0x00)\n\t\tself.LCD_WriteData_8bit(0x07)\n\t\tself.LCD_WriteData_8bit(0x03)\n\t\tself.LCD_WriteData_8bit(0x10) \n\t\t\n\t\t#Enable test command\n\t\tself.LCD_WriteReg(0xF0)\n\t\tself.LCD_WriteData_8bit(0x01)\n\t\t\n\t\t#Disable ram power save mode\n\t\tself.LCD_WriteReg(0xF6)\n\t\tself.LCD_WriteData_8bit(0x00)\n\t\t\n\t\t#65k mode\n\t\tself.LCD_WriteReg(0x3A)\n\t\tself.LCD_WriteData_8bit(0x05)\n\n\t#********************************************************************************\n\t#function:\tSet the display scan and color transfer modes\n\t#parameter: \n\t#\t\tScan_dir   :   Scan direction\n\t#\t\tColorchose :   RGB or GBR color format\n\t#********************************************************************************\n\tdef LCD_SetGramScanWay(self, Scan_dir):\n\t\t#Get the screen scan direction\n\t\tself.LCD_Scan_Dir = Scan_dir\n\t\t\n\t\t#Get GRAM and LCD width and height\n\t\tif (Scan_dir == L2R_U2D) or (Scan_dir == L2R_D2U) or (Scan_dir == R2L_U2D) or (Scan_dir == R2L_D2U) :\n\t\t\tself.width\t= LCD_HEIGHT \n\t\t\tself.height \t= LCD_WIDTH \n\t\t\tif Scan_dir == L2R_U2D:\n\t\t\t\tMemoryAccessReg_Data = 0X00 | 0x00\n\t\t\telif Scan_dir == L2R_D2U:\n\t\t\t\tMemoryAccessReg_Data = 0X00 | 0x80\n\t\t\telif Scan_dir == R2L_U2D:\n\t\t\t\tMemoryAccessReg_Data = 0x40 | 0x00\n\t\t\telse:\t\t#R2L_D2U:\n\t\t\t\tMemoryAccessReg_Data = 0x40 | 0x80\n\t\telse:\n\t\t\tself.width\t= LCD_WIDTH \n\t\t\tself.height \t= LCD_HEIGHT \n\t\t\tif Scan_dir == U2D_L2R:\n\t\t\t\tMemoryAccessReg_Data = 0X00 | 0x00 | 0x20\n\t\t\telif Scan_dir == U2D_R2L:\n\t\t\t\tMemoryAccessReg_Data = 0X00 | 0x40 | 0x20\n\t\t\telif Scan_dir == D2U_L2R:\n\t\t\t\tMemoryAccessReg_Data = 0x80 | 0x00 | 0x20\n\t\t\telse:\t\t#R2L_D2U\n\t\t\t\tMemoryAccessReg_Data = 0x40 | 0x80 | 0x20\n\t\t\n\t\t#please set (MemoryAccessReg_Data & 0x10) != 1\n\t\tif (MemoryAccessReg_Data & 0x10) != 1:\n\t\t\tself.LCD_X_Adjust = LCD_Y\n\t\t\tself.LCD_Y_Adjust = LCD_X\n\t\telse:\n\t\t\tself.LCD_X_Adjust = LCD_X\n\t\t\tself.LCD_Y_Adjust = LCD_Y\n\t\t\n\t\t# Set the read / write scan direction of the frame memory\n\t\tself.LCD_WriteReg(0x36)\t\t#MX, MY, RGB mode \n\t\tif LCD_1IN44 == 1:\n\t\t\tself.LCD_WriteData_8bit( MemoryAccessReg_Data | 0x08)\t#0x08 set RGB\n\t\telse:\n\t\t\tself.LCD_WriteData_8bit( MemoryAccessReg_Data & 0xf7)\t#RGB color filter panel\n\n\t#/********************************************************************************\n\t#function:\t\n\t#\t\t\tinitialization\n\t#********************************************************************************/\n\tdef LCD_Init(self, Lcd_ScanDir):\n\t\tif (config.GPIO_Init() != 0):\n\t\t\treturn -1\n\t\t\n\t\t#Turn on the backlight\n\t\t#GPIO.setup(config.LCD_BL_PIN, GPIO.OUT)\n\t\tGPIO.output(config.LCD_BL_PIN,GPIO.HIGH)\n\t\t\n\t\t#Hardware reset\n\t\tself.LCD_Reset()\n\t\t\n\t\t#Set the initialization register\n\t\tself.LCD_InitReg()\n\t\t\n\t\t#Set the display scan and color transfer modes\t\n\t\tself.LCD_SetGramScanWay(Lcd_ScanDir)\n\t\tconfig.Driver_Delay_ms(200)\n\t\t\n\t\t#sleep out\n\t\tself.LCD_WriteReg(0x11)\n\t\tconfig.Driver_Delay_ms(120)\n\t\t\n\t\t#Turn on the LCD display\n\t\tself.LCD_WriteReg(0x29)\n\t\t\n\t#/********************************************************************************\n\t#function:\tSets the start position and size of the display area\n\t#parameter: \n\t#\tXstart \t:   X direction Start coordinates\n\t#\tYstart  :   Y direction Start coordinates\n\t#\tXend    :   X direction end coordinates\n\t#\tYend    :   Y direction end coordinates\n\t#********************************************************************************/\n\tdef LCD_SetWindows(self, Xstart, Ystart, Xend, Yend):\n\t\t#set the X coordinates\n\t\tself.LCD_WriteReg(0x2A)\n\t\tself.LCD_WriteData_8bit(0x00)\n\t\tself.LCD_WriteData_8bit((Xstart & 0xff) + self.LCD_X_Adjust)\n\t\tself.LCD_WriteData_8bit(0x00)\n\t\tself.LCD_WriteData_8bit(((Xend - 1) & 0xff) + self.LCD_X_Adjust)\n\n\t\t#set the Y coordinates\n\t\tself.LCD_WriteReg (0x2B)\n\t\tself.LCD_WriteData_8bit(0x00)\n\t\tself.LCD_WriteData_8bit((Ystart & 0xff) + self.LCD_Y_Adjust)\n\t\tself.LCD_WriteData_8bit(0x00)\n\t\tself.LCD_WriteData_8bit(((Yend - 1) & 0xff )+ self.LCD_Y_Adjust)\n\n\t\tself.LCD_WriteReg(0x2C)\n\n\tdef LCD_Clear(self):\n\t\t#hello\n\t\t_buffer = [0xff]*(self.width * self.height * 2)\n\t\tself.LCD_SetWindows(0, 0, self.width, self.height)\n\t\tGPIO.output(config.LCD_DC_PIN, GPIO.HIGH)\n\t\tfor i in range(0,len(_buffer),4096):\n\t\t\tconfig.SPI_Write_Byte(_buffer[i:i+4096])\n\n\tdef LCD_ShowImage(self,Image,Xstart,Ystart):\n\t\tif (Image == None):\n\t\t\treturn\n\t\timwidth, imheight = Image.size\n\t\tif imwidth != self.width or imheight != self.height:\n\t\t\traise ValueError('Image must be same dimensions as display \\\n\t\t\t\t({0}x{1}).' .format(self.width, self.height))\n\t\timg = np.asarray(Image)\n\t\tpix = np.zeros((self.width,self.height,2), dtype = np.uint8)\n\t\tpix[...,[0]] = np.add(np.bitwise_and(img[...,[0]],0xF8),np.right_shift(img[...,[1]],5))\n\t\tpix[...,[1]] = np.add(np.bitwise_and(np.left_shift(img[...,[1]],3),0xE0),np.right_shift(img[...,[2]],3))\n\t\tpix = pix.flatten().tolist()\n\t\tself.LCD_SetWindows(0, 0, self.width , self.height)\n\t\tGPIO.output(config.LCD_DC_PIN, GPIO.HIGH)\n\t\tfor i in range(0,len(pix),4096):\n\t\t\tconfig.SPI_Write_Byte(pix[i:i+4096])\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat144/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat144/config.py",
    "content": "# /*****************************************************************************\n# * | File        :   config.py\n# * | Author      :\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-12-06\n# * | Info        :\n# ******************************************************************************/\nDevice_SPI = 1\nDevice_I2C = 0\nDevice = Device_SPI\n#spi = spidev.SpiDev(0, 0)\n\n##\n #  @filename   :   DEV_Config.py\n #  @brief      :   LCD hardware interface implements (GPIO, SPI)\n #  @author     :   Yehui from Waveshare\n #\n #  Copyright (C) Waveshare     July 10 2017\n #\n # Permission is hereby granted, free of charge, to any person obtaining a copy\n # of this software and associated documnetation files (the \"Software\"), to deal\n # in the Software without restriction, including without limitation the rights\n # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n # copies of the Software, and to permit persons to  whom the Software is\n # furished to do so, subject to the following conditions:\n #\n # The above copyright notice and this permission notice shall be included in\n # all copies or substantial portions of the Software.\n #\n # THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n # FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n # LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n # THE SOFTWARE.\n #\n \nimport spidev\nimport RPi.GPIO as GPIO\nimport time\n\n# Pin definition\nLCD_RST_PIN         = 27\nLCD_DC_PIN          = 25\nLCD_CS_PIN          = 8\nLCD_BL_PIN          = 24\n\n# SPI device, bus = 0, device = 0\nSPI = spidev.SpiDev(0, 0)\n\ndef epd_digital_write(pin, value):\n    GPIO.output(pin, value)\n\ndef Driver_Delay_ms(xms):\n    time.sleep(xms / 1000.0)\n\ndef SPI_Write_Byte(data):\n    SPI.writebytes(data)\n\ndef GPIO_Init():\n    GPIO.setmode(GPIO.BCM)\n    GPIO.setwarnings(False)\n    GPIO.setup(LCD_RST_PIN, GPIO.OUT)\n    GPIO.setup(LCD_DC_PIN, GPIO.OUT)\n    GPIO.setup(LCD_CS_PIN, GPIO.OUT)\n    GPIO.setup(LCD_BL_PIN, GPIO.OUT)\n    SPI.max_speed_hz = 9000000\n    SPI.mode = 0b00\n    return 0;\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/lcdhat144/epd.py",
    "content": "# Waveshare 1.44inch LCD HAT\n# https://www.waveshare.com/1.44inch-lcd-hat.htm\n# https://www.waveshare.com/wiki/1.44inch_LCD_HAT\n# Driver: ST7735S\n# Interface: SPI\n# Display color: RGB, 65K color\n# Resolution: 128x128\n# Backlight: LED\n# Operating voltage: 3.3V\n\nfrom . import config\nfrom . import LCD_1in44\nfrom PIL import ImageOps\n\nclass EPD(object):\n    def __init__(self):\n        self.width = 128\n        self.height = 128\n        self.LCD = LCD_1in44.LCD()\n        self.LCD.Lcd_ScanDir = LCD_1in44.SCAN_DIR_DFT  #SCAN_DIR_DFT = D2U_L2R\n        self.LCD.LCD_Init(self.LCD.Lcd_ScanDir)\n\n    def init(self):\n        pass\n\n    def clear(self):\n        #self.LCD.LCD_Clear()\n        pass\n\n    def display(self, image):\n        rgb_im = ImageOps.colorize(image.convert(\"L\"), black =\"green\", white =\"black\")\n        self.LCD.LCD_ShowImage(rgb_im, 0, 0)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/oledhat/SH1106.py",
    "content": "from . import config\nimport RPi.GPIO as GPIO\nimport time\n\nDevice_SPI = config.Device_SPI\nDevice_I2C = config.Device_I2C\n\nLCD_WIDTH   = 128 #LCD width\nLCD_HEIGHT  = 64  #LCD height\n\nclass SH1106(object):\n    def __init__(self):\n        self.width = LCD_WIDTH\n        self.height = LCD_HEIGHT\n        #Initialize DC RST pin\n        self._dc = config.DC_PIN\n        self._rst = config.RST_PIN\n        self._bl = config.BL_PIN\n        self.Device = config.Device\n\n\n    \"\"\"    Write register address and data     \"\"\"\n    def command(self, cmd):\n        if(self.Device == Device_SPI):\n            GPIO.output(self._dc, GPIO.LOW)\n            config.spi_writebyte([cmd])\n        else:\n            config.i2c_writebyte(0x00, cmd)\n\n    # def data(self, val):\n        # GPIO.output(self._dc, GPIO.HIGH)\n        # config.spi_writebyte([val])\n\n    def Init(self):\n        if (config.module_init() != 0):\n            return -1\n        \"\"\"Initialize display\"\"\"\n        self.reset()\n        self.command(0xAE);#--turn off oled panel\n        self.command(0x02);#---set low column address\n        self.command(0x10);#---set high column address\n        self.command(0x40);#--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)\n        self.command(0x81);#--set contrast control register\n        self.command(0xA0);#--Set SEG/Column Mapping\n        self.command(0xC0);#Set COM/Row Scan Direction\n        self.command(0xA6);#--set normal display\n        self.command(0xA8);#--set multiplex ratio(1 to 64)\n        self.command(0x3F);#--1/64 duty\n        self.command(0xD3);#-set display offset    Shift Mapping RAM Counter (0x00~0x3F)\n        self.command(0x00);#-not offset\n        self.command(0xd5);#--set display clock divide ratio/oscillator frequency\n        self.command(0x80);#--set divide ratio, Set Clock as 100 Frames/Sec\n        self.command(0xD9);#--set pre-charge period\n        self.command(0xF1);#Set Pre-Charge as 15 Clocks & Discharge as 1 Clock\n        self.command(0xDA);#--set com pins hardware configuration\n        self.command(0x12);\n        self.command(0xDB);#--set vcomh\n        self.command(0x40);#Set VCOM Deselect Level\n        self.command(0x20);#-Set Page Addressing Mode (0x00/0x01/0x02)\n        self.command(0x02);#\n        self.command(0xA4);# Disable Entire Display On (0xa4/0xa5)\n        self.command(0xA6);# Disable Inverse Display On (0xa6/a7)\n        time.sleep(0.1)\n        self.command(0xAF);#--turn on oled panel\n\n\n    def reset(self):\n        \"\"\"Reset the display\"\"\"\n        GPIO.output(self._rst,GPIO.HIGH)\n        time.sleep(0.1)\n        GPIO.output(self._rst,GPIO.LOW)\n        time.sleep(0.1)\n        GPIO.output(self._rst,GPIO.HIGH)\n        time.sleep(0.1)\n\n    def getbuffer(self, image):\n        # print \"bufsiz = \",(self.width/8) * self.height\n        buf = [0xFF] * ((self.width//8) * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        # print \"imwidth = %d, imheight = %d\",imwidth,imheight\n        if(imwidth == self.width and imheight == self.height):\n            #print (\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if pixels[x, y] == 0:\n                        buf[x + (y // 8) * self.width] &= ~(1 << (y % 8))\n                        # print x,y,x + (y * self.width)/8,buf[(x + y * self.width) / 8]\n\n        elif(imwidth == self.height and imheight == self.width):\n            #print (\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        buf[(newx + (newy // 8 )*self.width) ] &= ~(1 << (y % 8))\n        return buf\n\n\n    # def ShowImage(self,Image):\n        # self.SetWindows()\n        # GPIO.output(self._dc, GPIO.HIGH);\n        # for i in range(0,self.width * self.height/8):\n            # config.spi_writebyte([~Image[i]])\n\n    def ShowImage(self, pBuf):\n        for page in range(0,8):\n            # set page address #\n            self.command(0xB0 + page);\n            # set low column address #\n            self.command(0x02);\n            # set high column address #\n            self.command(0x10);\n            # write data #\n            time.sleep(0.01)\n            if(self.Device == Device_SPI):\n                GPIO.output(self._dc, GPIO.HIGH);\n            for i in range(0,self.width):#for(int i=0;i<self.width; i++)\n                if(self.Device == Device_SPI):\n                    config.spi_writebyte([~pBuf[i + self.width * page]]);\n                else :\n                    config.i2c_writebyte(0x40, ~pBuf[i + self.width * page])\n\n\n\n\n\n    def clear(self):\n        \"\"\"Clear contents of image buffer\"\"\"\n        _buffer = [0xff]*(self.width * self.height//8)\n        self.ShowImage(_buffer)\n            #print \"%d\",_buffer[i:i+4096]\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/oledhat/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/oledhat/config.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  config.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface,for Jetson nano\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-06\n# * | Info        :\n# ******************************************************************************/\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport RPi.GPIO as GPIO\nimport time\nfrom smbus import SMBus\nimport spidev\n\nimport ctypes\n# import spidev\n\n# Pin definition\nRST_PIN         = 25\nDC_PIN          = 24\nCS_PIN          = 8\nBL_PIN          = 18\nBUSY_PIN          = 18\n\nDevice_SPI = 1\nDevice_I2C = 0\n\n\n\nif(Device_SPI == 1):\n    Device = Device_SPI\n    spi = spidev.SpiDev(0, 0)\nelse :\n    Device = Device_I2C\n    address         = 0x3C\n    bus = SMBus(1)\n\ndef digital_write(pin, value):\n    GPIO.output(pin, value)\n\ndef digital_read(pin):\n    return GPIO.input(BUSY_PIN)\n\ndef delay_ms(delaytime):\n    time.sleep(delaytime / 1000.0)\n\ndef spi_writebyte(data):\n    # SPI.writebytes(data)\n    spi.writebytes([data[0]])\n\ndef i2c_writebyte(reg, value):\n    bus.write_byte_data(address, reg, value)\n\n    # time.sleep(0.01)\ndef module_init():\n    # print(\"module_init\")\n\n    GPIO.setmode(GPIO.BCM)\n    GPIO.setwarnings(False)\n    GPIO.setup(RST_PIN, GPIO.OUT)\n    GPIO.setup(DC_PIN, GPIO.OUT)\n    GPIO.setup(CS_PIN, GPIO.OUT)\n    GPIO.setup(BL_PIN, GPIO.OUT)\n\n\n    # SPI.max_speed_hz = 2000000\n    # SPI.mode = 0b00\n    # i2c_writebyte(0xff,0xff)\n    if(Device == Device_SPI):\n        # spi.SYSFS_software_spi_begin()\n        # spi.SYSFS_software_spi_setDataMode(0);\n        # spi.SYSFS_software_spi_setClockDivider(1);\n        spi.max_speed_hz = 2000000\n        spi.mode = 0b00\n\n    GPIO.output(CS_PIN, 0)\n    GPIO.output(BL_PIN, 1)\n    GPIO.output(DC_PIN, 0)\n    return 0\n\ndef module_exit():\n    if(Device == Device_SPI):\n        spi.SYSFS_software_spi_end()\n    else :\n        bus.close()\n    GPIO.output(RST_PIN, 0)\n    GPIO.output(DC_PIN, 0)\n\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/oledhat/epd.py",
    "content": "from . import SH1106\nfrom . import config\n\n# Display resolution\nEPD_WIDTH       = 64\nEPD_HEIGHT      = 128\n\ndisp = SH1106.SH1106()\n\nclass EPD(object):\n\n    def __init__(self):\n        self.reset_pin = config.RST_PIN\n        self.dc_pin = config.DC_PIN\n        self.busy_pin = config.BUSY_PIN\n        self.cs_pin = config.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    def init(self):\n        disp.Init()\n\n    def Clear(self):\n        disp.clear()\n\n    def display(self, image):\n        disp.ShowImage(disp.getbuffer(image))\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v1/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v1/epd2in13.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in13.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n\nimport logging\nfrom . import epdconfig\n\n# Display resolution\nEPD_WIDTH       = 122\nEPD_HEIGHT      = 250\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    lut_full_update = [\n        0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,\n        0x01, 0x00, 0x00, 0x00, 0x00, 0x00\n    ]\n\n    lut_partial_update  = [\n        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n    ]\n        \n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200) \n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(10)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)   \n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_command(self, command):\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n        \n    def ReadBusy(self):\n        while(epdconfig.digital_read(self.busy_pin) == 1):      # 0: idle, 1: busy\n            epdconfig.delay_ms(100)            \n\n    def TurnOnDisplay(self):\n        self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2\n        self.send_data(0xC4)\n        self.send_command(0x20) # MASTER_ACTIVATION\n        self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE\n\n        logging.debug(\"e-Paper busy\")\n        self.ReadBusy()\n        logging.debug(\"e-Paper busy release\")\n\n    def init(self, lut):\n        if (epdconfig.module_init() != 0):\n            return -1\n        # EPD hardware init start\n        self.reset()\n        self.send_command(0x01) # DRIVER_OUTPUT_CONTROL\n        self.send_data((EPD_HEIGHT - 1) & 0xFF)\n        self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF)\n        self.send_data(0x00) # GD = 0 SM = 0 TB = 0\n        \n        self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL\n        self.send_data(0xD7)\n        self.send_data(0xD6)\n        self.send_data(0x9D)\n        \n        self.send_command(0x2C) # WRITE_VCOM_REGISTER\n        self.send_data(0xA8) # VCOM 7C\n        \n        self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD\n        self.send_data(0x1A) # 4 dummy lines per gate\n        \n        self.send_command(0x3B) # SET_GATE_TIME\n        self.send_data(0x08) # 2us per line\n        \n        self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL\n        self.send_data(0x03)      \n        \n        self.send_command(0X11) # DATA_ENTRY_MODE_SETTING\n        self.send_data(0x03) # X increment; Y increment\n        \n        # WRITE_LUT_REGISTER\n        self.send_command(0x32)\n        for count in range(30):\n            self.send_data(lut[count])\n\n        return 0\n        \n##\n #  @brief: specify the memory area for data R/W\n ##\n    def SetWindows(self, x_start, y_start, x_end, y_end):\n        self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION\n        self.send_data((x_start >> 3) & 0xFF)\n        self.send_data((x_end >> 3) & 0xFF)\n        self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION\n        self.send_data(y_start & 0xFF)\n        self.send_data((y_start >> 8) & 0xFF)\n        self.send_data(y_end & 0xFF)\n        self.send_data((y_end >> 8) & 0xFF)\n\n##\n #  @brief: specify the start point for data R/W\n ##\n    def SetCursor(self, x, y):\n        self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER\n        # x point must be the multiple of 8 or the last 3 bits will be ignored\n        self.send_data((x >> 3) & 0xFF)\n        self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER\n        self.send_data(y & 0xFF)\n        self.send_data((y >> 8) & 0xFF)\n        self.ReadBusy()\n        \n    def getbuffer(self, image):\n        if self.width%8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n         \n        buf = [0xFF] * (linewidth * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        \n        if(imwidth == self.width and imheight == self.height):\n            for y in range(imheight):\n                for x in range(imwidth):                    \n                    if pixels[x, y] == 0:\n                        # x = imwidth - x\n                        buf[int(x / 8) + y * linewidth] &= ~(0x80 >> (x % 8))\n        elif(imwidth == self.height and imheight == self.width):\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        # newy = imwidth - newy - 1\n                        buf[int(newx / 8) + newy*linewidth] &= ~(0x80 >> (y % 8))\n        return buf   \n\n        \n    def display(self, image):\n        if self.width%8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n\n        self.SetWindows(0, 0, self.width, self.height);\n        for j in range(0, self.height):\n            self.SetCursor(0, j);\n            self.send_command(0x24);\n            for i in range(0, linewidth):\n                self.send_data(image[i + j * linewidth])   \n        self.TurnOnDisplay()\n    \n    def Clear(self, color):\n        if self.width%8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n\n        self.SetWindows(0, 0, self.width, self.height);\n        for j in range(0, self.height):\n            self.SetCursor(0, j);\n            self.send_command(0x24);\n            for i in range(0, linewidth):\n                self.send_data(color)   \n        self.TurnOnDisplay()\n\n    def sleep(self):\n        self.send_command(0x10) #enter deep sleep\n        self.send_data(0x01)\n        epdconfig.delay_ms(100)\n         \n        epdconfig.module_exit()\n        \n### END OF FILE ###\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v1/epd2in13bc.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in13bc.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nfrom . import epdconfig\nimport RPi.GPIO as GPIO\n# import numpy as np\n\n# Display resolution\nEPD_WIDTH       = 104\nEPD_HEIGHT      = 212\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, GPIO.HIGH)\n        epdconfig.delay_ms(200)\n        epdconfig.digital_write(self.reset_pin, GPIO.LOW)         # module reset\n        epdconfig.delay_ms(200)\n        epdconfig.digital_write(self.reset_pin, GPIO.HIGH)\n        epdconfig.delay_ms(200)\n\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, GPIO.LOW)\n        epdconfig.digital_write(self.cs_pin, GPIO.LOW)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, GPIO.HIGH)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, GPIO.HIGH)\n        epdconfig.digital_write(self.cs_pin, GPIO.LOW)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, GPIO.HIGH)\n\n    def ReadBusy(self):\n        epdconfig.delay_ms(20)\n        while(epdconfig.digital_read(self.busy_pin) == 0):      # 0: idle, 1: busy\n            epdconfig.delay_ms(100)\n\n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n        # EPD hardware init start\n        self.reset()\n\n        self.send_command(0x06) # BOOSTER_SOFT_START\n        self.send_data(0x17)\n        self.send_data(0x17)\n        self.send_data(0x17)\n\n        self.send_command(0x04) # POWER_ON\n        self.ReadBusy()\n\n        self.send_command(0x00) # PANEL_SETTING\n        self.send_data(0x8F)\n\n        self.send_command(0x50) # VCOM_AND_DATA_INTERVAL_SETTING\n        self.send_data(0xF0)\n\n        self.send_command(0x61) # RESOLUTION_SETTING\n        self.send_data(self.width & 0xff)\n        self.send_data(self.height >> 8)\n        self.send_data(self.height & 0xff)\n        return 0\n\n    def getbuffer(self, image):\n        buf = [0xFF] * (int(self.width/8) * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        if(imwidth == self.width and imheight == self.height):\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if pixels[x, y] == 0:\n                        buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))\n        elif(imwidth == self.height and imheight == self.width):\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))\n        return buf\n\n    def displayBlack(self, imageblack):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(imageblack[i])\n        self.send_command(0x92)\n\n        self.send_command(0x12) # REFRESH\n        self.ReadBusy()\n\n    def display(self, imageblack, imagecolor):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(imageblack[i])\n        self.send_command(0x92)\n\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(imagecolor[i])\n        self.send_command(0x92)\n\n        self.send_command(0x12) # REFRESH\n        self.ReadBusy()\n\n    def Clear(self):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        self.send_command(0x92)\n\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        self.send_command(0x92)\n\n        self.send_command(0x12) # REFRESH\n        self.ReadBusy()\n\n    def sleep(self):\n        self.send_command(0x02) # POWER_OFF\n        self.ReadBusy()\n        self.send_command(0x07) # DEEP_SLEEP\n        self.send_data(0xA5) # check code\n\n#        epdconfig.module_exit()\n### END OF FILE ###\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v1/epd2in13bcFAST.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in13d.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n\n# =============================================================================\n# THIS FILE HAS BEEN MODIFIED FROM ORIGINAL, IT HAS BEEN MODIFIED TO RUN THE\n# THREE COLOR WAVESHARE 2.13IN DISPLAY AT A MUCH, MUCH FASTER RATE THAN NORMAL\n# AND IT COULD DAMAGE YOUR DISPLAY. THERE IS NO WARRANTY INCLUDED AND YOU USE\n# THIS CODE AT YOUR OWN RISK. WE ARE NOT RESPONSIBLE FOR ANYTHING THAT HAPPENS\n# INCLUDING BUT NOT LIMITED TO: DESTRUCTION OF YOUR DISPLAY, PI, HOUSE, CAR,\n# SPACE-TIME-CONTINUUM, OR IF THE CODE KILLS YOUR CAT. IF YOU AREN'T WILLING TO \n# TAKE THESE RISKS, PLEASE DO NOT USE THIS CODE.\n# =============================================================================\n\n\nimport logging\nfrom . import epdconfig\nfrom PIL import Image\nimport RPi.GPIO as GPIO\n\n# Display resolution\nEPD_WIDTH       = 104\nEPD_HEIGHT      = 212\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    lut_vcomDC = [  \n        0x00, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x60, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x00, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x00, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00,\n    ]\n\n    lut_ww = [  \n        0x40, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x40, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bw = [  \n        0x40, 0x17, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x0F, 0x0F, 0x00, 0x00, 0x03,\n        0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,\n        0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_wb = [\n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bb = [ \n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x00,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    \n    lut_vcom1 = [  \n        0xA0, 0x10, 0x10, 0x00, 0x00, 0x02,\n        0x00, 0x10, 0x10, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00,\n    ]\n\n    lut_ww1 = [  \n        0x50, 0x01, 0x01, 0x00, 0x00, 0x01,\n        0xA0, 0x42, 0x42, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bw1 = [  \n        0x50, 0x01, 0x01, 0x00, 0x00, 0x01,\n        0xA0, 0x42, 0x42, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_wb1 = [\n        0xA0, 0x01, 0x01, 0x00, 0x00, 0x01,\n        0x50, 0x42, 0x42, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bb1 = [ \n        0xA0, 0x01, 0x01, 0x00, 0x00, 0x01,\n        0x50, 0x42, 0x42, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ] \n\n        \n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200) \n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(10)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)   \n\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n        \n    def ReadBusy(self):\n        logging.debug(\"e-Paper busy\")\n        while(epdconfig.digital_read(self.busy_pin) == 0):      # 0: idle, 1: busy\n            self.send_command(0x71)\n            epdconfig.delay_ms(100)  \n        logging.debug(\"e-Paper busy release\")\n        \n    def TurnOnDisplay(self):\n        self.send_command(0x12)\n        epdconfig.delay_ms(10)\n        self.ReadBusy()\n        \n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n        # EPD hardware init start\n        self.reset()\n        \n        self.send_command(0x01)\t# POWER SETTING\n        self.send_data(0x03)\n        self.send_data(0x00)\n        self.send_data(0x2b)\n        self.send_data(0x2b)\n        self.send_data(0x03)\n\n        self.send_command(0x06)\t# boost soft start\n        self.send_data(0x17) # A\n        self.send_data(0x17) # B\n        self.send_data(0x17) # C\n\n        self.send_command(0x04)\n        self.ReadBusy()\n\n        self.send_command(0x00)\t# panel setting\n        self.send_data(0xbf) # LUT from OTP,128x296\n        self.send_data(0x0d) # VCOM to 0V fast\n\n        self.send_command(0x30)\t# PLL setting\n        self.send_data(0x21) # 3a 100HZ   29 150Hz 39 200HZ\t31 171HZ\n\n        self.send_command(0x61)\t# resolution setting\n        self.send_data(self.width)\n        self.send_data((self.height >> 8) & 0xff)\n        self.send_data(self.height& 0xff)\n\n        self.send_command(0x82)\t# vcom_DC setting\n        self.send_data(0x28)\n        return 0\n        \n    def SetFullReg(self):\n        self.send_command(0x82)\n        self.send_data(0x00)\n        self.send_command(0X50)\n        self.send_data(0x97)\n#        self.send_command(0x00)\t# panel setting\n#        self.send_data(0x9f) # LUT from OTP,128x296\n\n    def SetPartReg(self):\n#        self.send_command(0x00)\t# panel setting\n#        self.send_data(0xbf) # LUT from OTP,128x296\n        self.send_command(0x82)\n        self.send_data(0x03)\n        self.send_command(0X50)\n        self.send_data(0x47)\n        \n        self.send_command(0x20) # vcom\n        for count in range(0, 44):\n            self.send_data(self.lut_vcom1[count])\n        self.send_command(0x21) # ww --\n        for count in range(0, 42):\n            self.send_data(self.lut_ww1[count])\n        self.send_command(0x22) # bw r\n        for count in range(0, 42):\n            self.send_data(self.lut_bw1[count])\n        self.send_command(0x23) # wb w\n        for count in range(0, 42):\n            self.send_data(self.lut_wb1[count])\n        self.send_command(0x24) # bb b\n        for count in range(0, 42):\n            self.send_data(self.lut_bb1[count])\n\n    def getbuffer(self, image):\n        # logging.debug(\"bufsiz = \",int(self.width/8) * self.height)\n        buf = [0xFF] * (int(self.width/8) * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        # logging.debug(\"imwidth = %d, imheight = %d\",imwidth,imheight)\n        if(imwidth == self.width and imheight == self.height):\n            logging.debug(\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if pixels[x, y] == 0:\n                        buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))\n        elif(imwidth == self.height and imheight == self.width):\n            logging.debug(\"Horizontal\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))\n        return buf\n\n    def display(self, image):\n        if (Image == None):\n            return\n            \n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0x00)\n        epdconfig.delay_ms(10)\n        \n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(image[i])\n        epdconfig.delay_ms(10)\n        \n        self.SetFullReg()\n        self.TurnOnDisplay()\n        \n    def DisplayPartial(self, image):   \n        if (Image == None):\n            return\n            \n        self.SetPartReg()\n        self.send_command(0x91)\n        self.send_command(0x90)\n        self.send_data(0)\n        self.send_data(self.width - 1)\n\n        self.send_data(0)\n        self.send_data(0)\n        self.send_data(int(self.height / 256))\n        self.send_data(self.height % 256 - 1)\n        self.send_data(0x28)\n            \n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(image[i])\n        epdconfig.delay_ms(10)\n        \n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(~image[i])\n        epdconfig.delay_ms(10)\n          \n        self.TurnOnDisplay()\n        \n    def Clear(self):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0x00)\n        epdconfig.delay_ms(10)\n        \n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0x00)\n        epdconfig.delay_ms(10)\n        \n        self.SetFullReg()\n        self.TurnOnDisplay()\n\n    def sleep(self):\n        self.send_command(0X50)\n        self.send_data(0xf7)\n        self.send_command(0X02) # power off\n        self.send_command(0X07) # deep sleep  \n        self.send_data(0xA5)\n\n        epdconfig.module_exit()\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v1/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-21\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n\n        # SPI device, bus = 0, device = 0\n        self.SPI = spidev.SpiDev(0, 0)\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.close()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v154inch/epd1in54b.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd1in54b.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport logging\nfrom . import epdconfig\n\n# Display resolution\nEPD_WIDTH       = 200\nEPD_HEIGHT      = 200\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    lut_vcom0 = [0x0E, 0x14, 0x01, 0x0A, 0x06, 0x04, 0x0A, 0x0A, 0x0F, 0x03, 0x03, 0x0C, 0x06, 0x0A, 0x00]\n    lut_w = [0x0E, 0x14, 0x01, 0x0A, 0x46, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x86, 0x0A, 0x04]\n    lut_b = [0x0E, 0x14, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x06, 0x4A, 0x04]\n    lut_g1 = [0x8E, 0x94, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x06, 0x0A, 0x04]\n    lut_g2 = [0x8E, 0x94, 0x01, 0x8A, 0x06, 0x04, 0x8A, 0x4A, 0x0F, 0x83, 0x43, 0x0C, 0x06, 0x0A, 0x04]\n    lut_vcom1 = [0x03, 0x1D, 0x01, 0x01, 0x08, 0x23, 0x37, 0x37, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]\n    lut_red0 = [0x83, 0x5D, 0x01, 0x81, 0x48, 0x23, 0x77, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]\n    lut_red1 = [0x03, 0x1D, 0x01, 0x01, 0x08, 0x23, 0x37, 0x37, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] \n    \n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200) \n        epdconfig.digital_write(self.reset_pin, 0) # module reset\n        epdconfig.delay_ms(10)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)   \n\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n        \n    def ReadBusy(self):\n        logging.debug(\"e-Paper busy\")\n        while(epdconfig.digital_read(self.busy_pin) == 0):\n            epdconfig.delay_ms(100)    \n        logging.debug(\"e-Paper busy release\")\n      \n    def set_lut_bw(self):\n        self.send_command(0x20) # vcom\n        for count in range(0, 15):\n            self.send_data(self.lut_vcom0[count])\n        self.send_command(0x21) # ww --\n        for count in range(0, 15):\n            self.send_data(self.lut_w[count])\n        self.send_command(0x22) # bw r\n        for count in range(0, 15):\n            self.send_data(self.lut_b[count])\n        self.send_command(0x23) # wb w\n        for count in range(0, 15):\n            self.send_data(self.lut_g1[count])\n        self.send_command(0x24) # bb b\n        for count in range(0, 15):\n            self.send_data(self.lut_g2[count])\n\n    def set_lut_red(self):\n        self.send_command(0x25)\n        for count in range(0, 15):\n            self.send_data(self.lut_vcom1[count])\n        self.send_command(0x26)\n        for count in range(0, 15):\n            self.send_data(self.lut_red0[count])\n        self.send_command(0x27)\n        for count in range(0, 15):\n            self.send_data(self.lut_red1[count])\n            \n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n        # EPD hardware init start\n        self.reset()\n        \n        self.send_command(0x01) # POWER_SETTING\n        self.send_data(0x07)\n        self.send_data(0x00)\n        self.send_data(0x08)\n        self.send_data(0x00)\n        self.send_command(0x06) # BOOSTER_SOFT_START\n        self.send_data(0x07)\n        self.send_data(0x07)\n        self.send_data(0x07)\n        self.send_command(0x04) # POWER_ON\n\n        self.ReadBusy()\n\n        self.send_command(0X00) # PANEL_SETTING\n        self.send_data(0xCF)\n        self.send_command(0X50) # VCOM_AND_DATA_INTERVAL_SETTING\n        self.send_data(0x17)\n        self.send_command(0x30) # PLL_CONTROL\n        self.send_data(0x39)\n        self.send_command(0x61) # TCON_RESOLUTION set x and y\n        self.send_data(0xC8)\n        self.send_data(0x00)\n        self.send_data(0xC8)\n        self.send_command(0x82) # VCM_DC_SETTING_REGISTER\n        self.send_data(0x0E)\n        \n        self.set_lut_bw()\n        self.set_lut_red()\n        return 0\n\n    def getbuffer(self, image):\n        buf = [0xFF] * int(self.width * self.height / 8)\n        # Set buffer to value of Python Imaging Library image.\n        # Image must be in mode 1.\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        if imwidth != self.width or imheight != self.height:\n            raise ValueError('Image must be same dimensions as display \\\n                ({0}x{1}).' .format(self.width, self.height))\n\n        pixels = image_monocolor.load()\n        for y in range(self.height):\n            for x in range(self.width):\n                # Set the bits for the column of pixels at the current position.\n                if pixels[x, y] == 0:\n                    buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))\n        return buf\n\n    def display(self, blackimage, redimage):\n        # send black data\n        if (blackimage != None):\n            self.send_command(0x10) # DATA_START_TRANSMISSION_1\n            for i in range(0, int(self.width * self.height / 8)):\n                temp = 0x00\n                for bit in range(0, 4):\n                    if (blackimage[i] & (0x80 >> bit) != 0):\n                        temp |= 0xC0 >> (bit * 2)\n                self.send_data(temp)  \n                temp = 0x00\n                for bit in range(4, 8):\n                    if (blackimage[i] & (0x80 >> bit) != 0):\n                        temp |= 0xC0 >> ((bit - 4) * 2)\n                self.send_data(temp)\n                \n        # send red data        \n        if (redimage != None):\n            self.send_command(0x13) # DATA_START_TRANSMISSION_2\n            for i in range(0, int(self.width * self.height / 8)):\n                self.send_data(redimage[i])  \n\n        self.send_command(0x12) # DISPLAY_REFRESH\n        self.ReadBusy()\n\n    def Clear(self):\n        self.send_command(0x10) # DATA_START_TRANSMISSION_1\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n            self.send_data(0xFF)\n            \n        self.send_command(0x13) # DATA_START_TRANSMISSION_2\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n\n        self.send_command(0x12) # DISPLAY_REFRESH\n        self.ReadBusy()\n\n    def sleep(self):\n        self.send_command(0x50) # VCOM_AND_DATA_INTERVAL_SETTING\n        self.send_data(0x17)\n        self.send_command(0x82) # to solve Vcom drop \n        self.send_data(0x00)        \n        self.send_command(0x01) # power setting      \n        self.send_data(0x02) # gate switch to external\n        self.send_data(0x00)\n        self.send_data(0x00) \n        self.send_data(0x00) \n        self.ReadBusy()\n        \n        self.send_command(0x02) # power off\n        \n        epdconfig.module_exit()\n\n### END OF FILE ###\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v154inch/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-21\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n\n        # SPI device, bus = 0, device = 0\n        self.SPI = spidev.SpiDev(0, 0)\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.close()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v2/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v2/waveshare.py",
    "content": "# //*****************************************************************************\r\n# * | File        :\t  epd2in13.py\r\n# * | Author      :   Waveshare team\r\n# * | Function    :   Electronic paper driver\r\n# * | Info        :\r\n# *----------------\r\n# * |\tThis version:   V3.0\r\n# * | Date        :   2018-11-01\r\n# * | Info        :   python2 demo\r\n# * 1.Remove:\r\n#   digital_write(self, pin, value)\r\n#   digital_read(self, pin)\r\n#   delay_ms(self, delaytime)\r\n#   set_lut(self, lut)\r\n#   self.lut = self.lut_full_update\r\n# * 2.Change:\r\n#   display_frame -> TurnOnDisplay\r\n#   set_memory_area -> SetWindow\r\n#   set_memory_pointer -> SetCursor\r\n# * 3.How to use\r\n#   epd = epd2in13.EPD()\r\n#   epd.init(epd.lut_full_update)\r\n#   image = Image.new('1', (epd2in13.EPD_WIDTH, epd2in13.EPD_HEIGHT), 255)\r\n#   ...\r\n#   drawing ......\r\n#   ...\r\n#   epd.display(getbuffer(image))\r\n# ******************************************************************************//\r\n# Permission is hereby granted, free of charge, to any person obtaining a copy\r\n# of this software and associated documentation files (the \"Software\"), to deal\r\n# in the Software without restriction, including without limitation the rights\r\n# to use, copy, modify, merge, publish, distribute, sublicense, and//or sell\r\n# copies of the Software, and to permit persons to  whom the Software is\r\n# furnished to do so, subject to the following conditions:\r\n#\r\n# The above copyright notice and this permission notice shall be included in\r\n# all copies or substantial portions of the Software.\r\n#\r\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n# THE SOFTWARE.\r\n#\r\n\r\nimport time\r\nimport spidev\r\nimport RPi.GPIO as GPIO\r\nfrom PIL import Image\r\n\r\n# Pin definition\r\nRST_PIN = 17\r\nDC_PIN = 25\r\nCS_PIN = 8\r\nBUSY_PIN = 24\r\n\r\n# SPI device, bus = 0, device = 0\r\nSPI = spidev.SpiDev(0, 0)\r\n\r\n\r\ndef digital_write(pin, value):\r\n    GPIO.output(pin, value)\r\n\r\n\r\ndef digital_read(pin):\r\n    return GPIO.input(BUSY_PIN)\r\n\r\n\r\ndef delay_ms(delaytime):\r\n    time.sleep(delaytime / 1000.0)\r\n\r\n\r\ndef spi_writebyte(data):\r\n    SPI.writebytes(data)\r\n\r\n\r\ndef module_init():\r\n    GPIO.setmode(GPIO.BCM)\r\n    GPIO.setwarnings(False)\r\n    GPIO.setup(RST_PIN, GPIO.OUT)\r\n    GPIO.setup(DC_PIN, GPIO.OUT)\r\n    GPIO.setup(CS_PIN, GPIO.OUT)\r\n    GPIO.setup(BUSY_PIN, GPIO.IN)\r\n    SPI.max_speed_hz = 2000000\r\n    SPI.mode = 0b00\r\n    return 0;\r\n\r\n\r\n# Display resolution\r\nEPD_WIDTH = 122\r\nEPD_HEIGHT = 250\r\n\r\n\r\nclass EPD:\r\n    def __init__(self):\r\n        self.reset_pin = RST_PIN\r\n        self.dc_pin = DC_PIN\r\n        self.busy_pin = BUSY_PIN\r\n        self.width = EPD_WIDTH\r\n        self.height = EPD_HEIGHT\r\n\r\n    FULL_UPDATE = 0\r\n    PART_UPDATE = 1\r\n    lut_full_update = [\r\n        0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00,  # LUT0: BB:     VS 0 ~7\r\n        0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00,  # LUT1: BW:     VS 0 ~7\r\n        0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00,  # LUT2: WB:     VS 0 ~7\r\n        0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00,  # LUT3: WW:     VS 0 ~7\r\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  # LUT4: VCOM:   VS 0 ~7\r\n\r\n        0x03, 0x03, 0x00, 0x00, 0x02,  # TP0 A~D RP0\r\n        0x09, 0x09, 0x00, 0x00, 0x02,  # TP1 A~D RP1\r\n        0x03, 0x03, 0x00, 0x00, 0x02,  # TP2 A~D RP2\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP3 A~D RP3\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP4 A~D RP4\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP5 A~D RP5\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP6 A~D RP6\r\n\r\n        0x15, 0x41, 0xA8, 0x32, 0x30, 0x0A,\r\n    ]\r\n\r\n    lut_partial_update = [  # 20 bytes\r\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  # LUT0: BB:     VS 0 ~7\r\n        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  # LUT1: BW:     VS 0 ~7\r\n        0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  # LUT2: WB:     VS 0 ~7\r\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  # LUT3: WW:     VS 0 ~7\r\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  # LUT4: VCOM:   VS 0 ~7\r\n\r\n        0x0A, 0x00, 0x00, 0x00, 0x00,  # TP0 A~D RP0\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP1 A~D RP1\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP2 A~D RP2\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP3 A~D RP3\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP4 A~D RP4\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP5 A~D RP5\r\n        0x00, 0x00, 0x00, 0x00, 0x00,  # TP6 A~D RP6\r\n\r\n        0x15, 0x41, 0xA8, 0x32, 0x30, 0x0A,\r\n    ]\r\n\r\n    # Hardware reset\r\n    def reset(self):\r\n        digital_write(self.reset_pin, GPIO.HIGH)\r\n        delay_ms(200)\r\n        digital_write(self.reset_pin, GPIO.LOW)  # module reset\r\n        delay_ms(200)\r\n        digital_write(self.reset_pin, GPIO.HIGH)\r\n        delay_ms(200)\r\n\r\n    def send_command(self, command):\r\n        digital_write(self.dc_pin, GPIO.LOW)\r\n        spi_writebyte([command])\r\n\r\n    def send_data(self, data):\r\n        digital_write(self.dc_pin, GPIO.HIGH)\r\n        spi_writebyte([data])\r\n\r\n    def wait_until_idle(self):\r\n        while (digital_read(self.busy_pin) == 1):  # 0: idle, 1: busy\r\n            delay_ms(100)\r\n\r\n    def TurnOnDisplay(self):\r\n        self.send_command(0x22)\r\n        self.send_data(0xC7)\r\n        self.send_command(0x20)\r\n        self.wait_until_idle()\r\n\r\n    def init(self, update):\r\n        if (module_init() != 0):\r\n            return -1\r\n        # EPD hardware init start\r\n        self.reset()\r\n        if (update == self.FULL_UPDATE):\r\n            self.wait_until_idle()\r\n            self.send_command(0x12)  # soft reset\r\n            self.wait_until_idle()\r\n\r\n            self.send_command(0x74)  # set analog block control\r\n            self.send_data(0x54)\r\n            self.send_command(0x7E)  # set digital block control\r\n            self.send_data(0x3B)\r\n\r\n            self.send_command(0x01)  # Driver output control\r\n            self.send_data(0xF9)\r\n            self.send_data(0x00)\r\n            self.send_data(0x00)\r\n\r\n            self.send_command(0x11)  # data entry mode\r\n            self.send_data(0x01)\r\n\r\n            self.send_command(0x44)  # set Ram-X address start//end position\r\n            self.send_data(0x00)\r\n            self.send_data(0x0F)  # 0x0C-->(15+1)*8=128\r\n\r\n            self.send_command(0x45)  # set Ram-Y address start//end position\r\n            self.send_data(0xF9)  # 0xF9-->(249+1)=250\r\n            self.send_data(0x00)\r\n            self.send_data(0x00)\r\n            self.send_data(0x00)\r\n\r\n            self.send_command(0x3C)  # BorderWavefrom\r\n            self.send_data(0x03)\r\n\r\n            self.send_command(0x2C)  # VCOM Voltage\r\n            self.send_data(0x55)  #\r\n\r\n            self.send_command(0x03)\r\n            self.send_data(self.lut_full_update[70])\r\n\r\n            self.send_command(0x04)  #\r\n            self.send_data(self.lut_full_update[71])\r\n            self.send_data(self.lut_full_update[72])\r\n            self.send_data(self.lut_full_update[73])\r\n\r\n            self.send_command(0x3A)  # Dummy Line\r\n            self.send_data(self.lut_full_update[74])\r\n            self.send_command(0x3B)  # Gate time\r\n            self.send_data(self.lut_full_update[75])\r\n\r\n            self.send_command(0x32)\r\n            for count in range(70):\r\n                self.send_data(self.lut_full_update[count])\r\n\r\n            self.send_command(0x4E)  # set RAM x address count to 0\r\n            self.send_data(0x00)\r\n            self.send_command(0x4F)  # set RAM y address count to 0X127\r\n            self.send_data(0xF9)\r\n            self.send_data(0x00)\r\n            self.wait_until_idle()\r\n        else:\r\n            self.send_command(0x2C)  # VCOM Voltage\r\n            self.send_data(0x26)\r\n\r\n            self.wait_until_idle()\r\n\r\n            self.send_command(0x32)\r\n            for count in range(70):\r\n                self.send_data(self.lut_partial_update[count])\r\n\r\n            self.send_command(0x37)\r\n            self.send_data(0x00)\r\n            self.send_data(0x00)\r\n            self.send_data(0x00)\r\n            self.send_data(0x00)\r\n            self.send_data(0x40)\r\n            self.send_data(0x00)\r\n            self.send_data(0x00)\r\n\r\n            self.send_command(0x22)\r\n            self.send_data(0xC0)\r\n            self.send_command(0x20)\r\n            self.wait_until_idle()\r\n\r\n            self.send_command(0x3C)  # BorderWavefrom\r\n            self.send_data(0x01)\r\n        return 0\r\n\r\n    def getbuffer(self, image):\r\n        if self.width % 8 == 0:\r\n            linewidth = self.width // 8\r\n        else:\r\n            linewidth = self.width // 8 + 1\r\n\r\n        buf = [0xFF] * (linewidth * self.height)\r\n        image_monocolor = image.convert('1')\r\n        imwidth, imheight = image_monocolor.size\r\n        pixels = image_monocolor.load()\r\n\r\n        if (imwidth == self.width and imheight == self.height):\r\n            # print(\"Vertical\")\r\n            for y in range(imheight):\r\n                for x in range(imwidth):\r\n                    if pixels[x, y] == 0:\r\n                        x = imwidth - x\r\n                        buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8))\r\n        elif (imwidth == self.height and imheight == self.width):\r\n            # print(\"Horizontal\")\r\n            for y in range(imheight):\r\n                for x in range(imwidth):\r\n                    newx = y\r\n                    newy = self.height - x - 1\r\n                    if pixels[x, y] == 0:\r\n                        newy = imwidth - newy - 1\r\n                        buf[newx // 8 + newy * linewidth] &= ~(0x80 >> (y % 8))\r\n        return buf\r\n\r\n    def display(self, image):\r\n        if self.width % 8 == 0:\r\n            linewidth = self.width // 8\r\n        else:\r\n            linewidth = self.width // 8 + 1\r\n\r\n        self.send_command(0x24)\r\n        for j in range(0, self.height):\r\n            for i in range(0, linewidth):\r\n                self.send_data(image[i + j * linewidth])\r\n        self.TurnOnDisplay()\r\n\r\n    def displayPartial(self, image):\r\n        if self.width % 8 == 0:\r\n            linewidth = self.width // 8\r\n        else:\r\n            linewidth = self.width // 8 + 1\r\n\r\n        self.send_command(0x24)\r\n        for j in range(0, self.height):\r\n            for i in range(0, linewidth):\r\n                self.send_data(image[i + j * linewidth])\r\n        self.send_command(0x26)\r\n        for j in range(0, self.height):\r\n            for i in range(0, linewidth):\r\n                self.send_data(~image[i + j * linewidth])\r\n        self.TurnOnDisplay()\r\n\r\n    def Clear(self, color):\r\n        if self.width % 8 == 0:\r\n            linewidth = self.width // 8\r\n        else:\r\n            linewidth = self.width // 8 + 1\r\n        # print(linewidth)\r\n\r\n        self.send_command(0x24)\r\n        for j in range(0, self.height):\r\n            for i in range(0, linewidth):\r\n                self.send_data(color)\r\n        self.TurnOnDisplay()\r\n\r\n    def sleep(self):\r\n        self.send_command(0x22)  # POWER OFF\r\n        self.send_data(0xC3)\r\n        self.send_command(0x20)\r\n\r\n        self.send_command(0x10)  # enter deep sleep\r\n        self.send_data(0x01)\r\n        delay_ms(100)\r\n\r\n    ### END OF FILE ###"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v213bc/epd2in13bc.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in13bc.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport logging\nfrom . import epdconfig\nfrom PIL import Image\n\n# Display resolution\nEPD_WIDTH       = 104\nEPD_HEIGHT      = 212\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n\n    lut_vcomDC = [\n        0x00, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x60, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x00, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x00, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00,\n    ]\n\n    lut_ww = [\n        0x40, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x40, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bw = [\n        0x40, 0x17, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x0F, 0x0F, 0x00, 0x00, 0x03,\n        0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,\n        0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_wb = [\n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bb = [\n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_vcom1 = [\n        0x00, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00,\n    ]\n\n    lut_ww1 = [\n        0x00, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bw1 = [\n        0x80, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_wb1 = [\n        0x40, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bb1 = [\n        0x00, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n\n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)\n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(10)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)\n\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def ReadBusy(self):\n        logging.debug(\"e-Paper busy\")\n        while(epdconfig.digital_read(self.busy_pin) == 0):      # 0: idle, 1: busy\n            epdconfig.delay_ms(100)\n        logging.debug(\"e-Paper busy release\")\n\n    def TurnOnDisplay(self):\n        self.send_command(0x12)\n        epdconfig.delay_ms(10)\n        self.ReadBusy()\n\n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n\n        logging.debug(\"e-Paper 2.13bc preboot Freeze recovery\")\n        while(epdconfig.digital_read(self.busy_pin) == 0):      # 0: idle, 1: busy\n            epdconfig.delay_ms(100)\n            self.reset()\n            epdconfig.delay_ms(200)\n            self.send_command(0x01)\t# POWER SETTING\n            self.send_data(0x03)\n            self.send_data(0x00)\n            self.send_data(0x2b)\n            self.send_data(0x2b)\n            self.send_data(0x03)\n            epdconfig.delay_ms(200)\n            self.send_command(0x06) # BOOSTER_SOFT_START\n            self.send_data(0x17)\n            self.send_data(0x17)\n            self.send_data(0x17)\n            self.send_command(0x04) # POWER_ON\n            epdconfig.delay_ms(200)\n            self.send_command(0X50)\n            self.send_data(0xf7)\n            self.send_command(0X02) # power off\n            self.send_command(0X07) # deep sleep\n            self.send_data(0xA5)\n            epdconfig.GPIO.output(epdconfig.RST_PIN, 0)\n            epdconfig.GPIO.output(epdconfig.DC_PIN, 0)\n            epdconfig.GPIO.output(epdconfig.CS_PIN, 0)\n            #logging.debug(\"Reset, powerdown, voltage off done\")\n        logging.debug(\"e-Paper is not frozen now :)\")\n\n\n        self.reset()\n\n        self.send_command(0x01)\t# POWER SETTING\n        self.send_data(0x03)\n        self.send_data(0x00)\n        self.send_data(0x2b)\n        self.send_data(0x2b)\n        self.send_data(0x03)\n\n        self.send_command(0x06) # BOOSTER_SOFT_START\n        self.send_data(0x17)\n        self.send_data(0x17)\n        self.send_data(0x17)\n\n        self.send_command(0x04) # POWER_ON\n        logging.debug(\"e-Paper 2.13bc bootup busy\")\n        while(epdconfig.digital_read(self.busy_pin) == 0):      # 0: idle, 1: busy\n            epdconfig.delay_ms(100)\n\n#        self.send_command(0x00) # PANEL_SETTING\n#        self.send_data(0x8F)\n#        self.send_command(0x50) # VCOM_AND_DATA_INTERVAL_SETTING\n#        self.send_data(0xF0)\n#        self.send_command(0x61) # RESOLUTION_SETTING\n#        self.send_data(self.width & 0xff)\n#        self.send_data(self.height >> 8)\n#        self.send_data(self.height & 0xff)\n\n        self.send_command(0x00)\t# panel setting\n        self.send_data(0xbf) # LUT from OTP,128x296\n        self.send_data(0x0d) # VCOM to 0V fast\n\n        self.send_command(0x30)\t# PLL setting\n        self.send_data(0x3a) # 3a 100HZ   29 150Hz 39 200HZ\t31 171HZ\n\n        self.send_command(0x61)\t# resolution setting\n        self.send_data(self.width & 0xff)\n        self.send_data((self.height >> 8) & 0xff)\n        self.send_data(self.height& 0xff)\n\n        self.send_command(0x82)\t# vcom_DC setting\n        self.send_data(0x28)\n\n        #self.Clear()\n        logging.debug(\"e-Paper booted\")\n        return 0\n\n    def SetFullReg(self):\n        self.send_command(0x82)\n        self.send_data(0x00)\n        self.send_command(0X50)\n        self.send_data(0x97)\n\n        self.send_command(0x20) # vcom\n        for count in range(0, 44):\n            self.send_data(self.lut_vcomDC[count])\n        self.send_command(0x21) # ww --\n        for count in range(0, 42):\n            self.send_data(self.lut_ww[count])\n        self.send_command(0x22) # bw r\n        for count in range(0, 42):\n            self.send_data(self.lut_bw[count])\n        self.send_command(0x23) # wb w\n        for count in range(0, 42):\n            self.send_data(self.lut_wb[count])\n        self.send_command(0x24) # bb b\n        for count in range(0, 42):\n            self.send_data(self.lut_bb[count])\n\n\n    def getbuffer(self, image):\n        # logging.debug(\"bufsiz = \",int(self.width/8) * self.height)\n        buf = [0xFF] * (int(self.width/8) * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        # logging.debug(\"imwidth = %d, imheight = %d\",imwidth,imheight)\n        if(imwidth == self.width and imheight == self.height):\n            logging.debug(\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if pixels[x, y] == 0:\n                        buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))\n        elif(imwidth == self.height and imheight == self.width):\n            logging.debug(\"Horizontal\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))\n        return buf\n\n    def display(self, imageblack, imagered):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(imageblack[i])\n        self.send_command(0x92)\n\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(imagered[i])\n        self.send_command(0x92)\n\n        self.send_command(0x12) # REFRESH\n        self.ReadBusy()\n\n    def pwndisplay(self, imageblack):\n        if (Image == None):\n            return\n\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0x00)\n        epdconfig.delay_ms(10)\n\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(imageblack[i])\n        epdconfig.delay_ms(10)\n\n        self.SetFullReg()\n        self.TurnOnDisplay()\n\n\n    def Clear(self):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        self.send_command(0x92)\n\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        self.send_command(0x92)\n\n        self.send_command(0x12) # REFRESH\n        self.ReadBusy()\n\n    def pwnclear(self):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        epdconfig.delay_ms(10)\n\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        epdconfig.delay_ms(10)\n\n        self.SetFullReg()\n        self.TurnOnDisplay()\n\n    def sleep(self):\n        self.send_command(0x02) # POWER_OFF\n        self.ReadBusy()\n        self.send_command(0x07) # DEEP_SLEEP\n        self.send_data(0xA5) # check code\n\n        epdconfig.module_exit()\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v213bc/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-21\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n\n        # SPI device, bus = 0, device = 0\n        self.SPI = spidev.SpiDev(0, 0)\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.close()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v213d/epd2in13d.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in13d.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n\nimport logging\nfrom . import epdconfig\nfrom PIL import Image\nimport RPi.GPIO as GPIO\n\n# Display resolution\nEPD_WIDTH       = 104\nEPD_HEIGHT      = 212\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    lut_vcomDC = [  \n        0x00, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x60, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x00, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x00, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00,\n    ]\n\n    lut_ww = [  \n        0x40, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x40, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bw = [  \n        0x40, 0x17, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x0F, 0x0F, 0x00, 0x00, 0x03,\n        0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,\n        0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_wb = [\n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bb = [ \n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    \n    lut_vcom1 = [  \n        0x00, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00,\n    ]\n\n    lut_ww1 = [  \n        0x00, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bw1 = [  \n        0x80, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_wb1 = [\n        0x40, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n\n    lut_bb1 = [ \n        0x00, 0x19, 0x01, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n        \n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200) \n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(10)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)   \n\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n        \n    def ReadBusy(self):\n        logging.debug(\"e-Paper busy\")\n        while(epdconfig.digital_read(self.busy_pin) == 0):      # 0: idle, 1: busy\n            self.send_command(0x71)\n            epdconfig.delay_ms(100)  \n        logging.debug(\"e-Paper busy release\")\n        \n    def TurnOnDisplay(self):\n        self.send_command(0x12)\n        epdconfig.delay_ms(10)\n        self.ReadBusy()\n        \n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n        # EPD hardware init start\n        self.reset()\n        \n        self.send_command(0x01)\t# POWER SETTING\n        self.send_data(0x03)\n        self.send_data(0x00)\n        self.send_data(0x2b)\n        self.send_data(0x2b)\n        self.send_data(0x03)\n\n        self.send_command(0x06)\t# boost soft start\n        self.send_data(0x17) # A\n        self.send_data(0x17) # B\n        self.send_data(0x17) # C\n\n        self.send_command(0x04)\n        self.ReadBusy()\n\n        self.send_command(0x00)\t# panel setting\n        self.send_data(0xbf) # LUT from OTP,128x296\n        self.send_data(0x0d) # VCOM to 0V fast\n\n        self.send_command(0x30)\t# PLL setting\n        self.send_data(0x3a) # 3a 100HZ   29 150Hz 39 200HZ\t31 171HZ\n\n        self.send_command(0x61)\t# resolution setting\n        self.send_data(self.width)\n        self.send_data((self.height >> 8) & 0xff)\n        self.send_data(self.height& 0xff)\n\n        self.send_command(0x82)\t# vcom_DC setting\n        self.send_data(0x28)\n        return 0\n        \n    def SetFullReg(self):\n        self.send_command(0x82)\n        self.send_data(0x00)\n        self.send_command(0X50)\n        self.send_data(0x97)\n        \n        self.send_command(0x20) # vcom\n        for count in range(0, 44):\n            self.send_data(self.lut_vcomDC[count])\n        self.send_command(0x21) # ww --\n        for count in range(0, 42):\n            self.send_data(self.lut_ww[count])\n        self.send_command(0x22) # bw r\n        for count in range(0, 42):\n            self.send_data(self.lut_bw[count])\n        self.send_command(0x23) # wb w\n        for count in range(0, 42):\n            self.send_data(self.lut_wb[count])\n        self.send_command(0x24) # bb b\n        for count in range(0, 42):\n            self.send_data(self.lut_bb[count])\n    \n    def SetPartReg(self):\n        self.send_command(0x82)\n        self.send_data(0x03)\n        self.send_command(0X50)\n        self.send_data(0x47)\n        \n        self.send_command(0x20) # vcom\n        for count in range(0, 44):\n            self.send_data(self.lut_vcom1[count])\n        self.send_command(0x21) # ww --\n        for count in range(0, 42):\n            self.send_data(self.lut_ww1[count])\n        self.send_command(0x22) # bw r\n        for count in range(0, 42):\n            self.send_data(self.lut_bw1[count])\n        self.send_command(0x23) # wb w\n        for count in range(0, 42):\n            self.send_data(self.lut_wb1[count])\n        self.send_command(0x24) # bb b\n        for count in range(0, 42):\n            self.send_data(self.lut_bb1[count])\n\n    def getbuffer(self, image):\n        # logging.debug(\"bufsiz = \",int(self.width/8) * self.height)\n        buf = [0xFF] * (int(self.width/8) * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        # logging.debug(\"imwidth = %d, imheight = %d\",imwidth,imheight)\n        if(imwidth == self.width and imheight == self.height):\n            logging.debug(\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if pixels[x, y] == 0:\n                        buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))\n        elif(imwidth == self.height and imheight == self.width):\n            logging.debug(\"Horizontal\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))\n        return buf\n\n    def display(self, image):\n        if (Image == None):\n            return\n            \n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0x00)\n        epdconfig.delay_ms(10)\n        \n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(image[i])\n        epdconfig.delay_ms(10)\n        \n        self.SetFullReg()\n        self.TurnOnDisplay()\n        \n    def DisplayPartial(self, image):   \n        if (Image == None):\n            return\n            \n        self.SetPartReg()\n        self.send_command(0x91)\n        self.send_command(0x90)\n        self.send_data(0)\n        self.send_data(self.width - 1)\n\n        self.send_data(0)\n        self.send_data(0)\n        self.send_data(int(self.height / 256))\n        self.send_data(self.height % 256 - 1)\n        self.send_data(0x28)\n            \n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(image[i])\n        epdconfig.delay_ms(10)\n        \n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(~image[i])\n        epdconfig.delay_ms(10)\n          \n        self.TurnOnDisplay()\n        \n    def Clear(self):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0x00)\n        epdconfig.delay_ms(10)\n        \n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        epdconfig.delay_ms(10)\n        \n        self.SetFullReg()\n        self.TurnOnDisplay()\n\n    def sleep(self):\n        self.send_command(0X50)\n        self.send_data(0xf7)\n        self.send_command(0X02) # power off\n        self.send_command(0X07) # deep sleep  \n        self.send_data(0xA5)\n\n        epdconfig.module_exit()\n\n### END OF FILE ###\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v213d/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-21\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n\n        # SPI device, bus = 0, device = 0\n        self.SPI = spidev.SpiDev(0, 0)\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.close()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epd2in13b_V4.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in13b_V4.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2022-04-21\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport logging\nfrom . import epdconfig\n\n# Display resolution\nEPD_WIDTH = 122\nEPD_HEIGHT = 250\n\nlogger = logging.getLogger(__name__)\n\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    # hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(20)\n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(2)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(20)\n\n    # send 1 byte command\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    # send 1 byte data\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    # send a lot of data\n    def send_data2(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte2(data)\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    # judge e-Paper whether is busy\n    def busy(self):\n        logger.debug(\"e-Paper busy\")\n        while (epdconfig.digital_read(self.busy_pin) != 0):\n            epdconfig.delay_ms(10)\n        logger.debug(\"e-Paper busy release\")\n\n    # set the display window\n    def set_windows(self, xstart, ystart, xend, yend):\n        self.send_command(0x44)  # SET_RAM_X_ADDRESS_START_END_POSITION\n        self.send_data((xstart >> 3) & 0xff)\n        self.send_data((xend >> 3) & 0xff)\n\n        self.send_command(0x45)  # SET_RAM_Y_ADDRESS_START_END_POSITION\n        self.send_data(ystart & 0xff)\n        self.send_data((ystart >> 8) & 0xff)\n        self.send_data(yend & 0xff)\n        self.send_data((yend >> 8) & 0xff)\n\n    # set the display cursor(origin)\n    def set_cursor(self, xstart, ystart):\n        self.send_command(0x4E)  # SET_RAM_X_ADDRESS_COUNTER\n        self.send_data(xstart & 0xff)\n\n        self.send_command(0x4F)  # SET_RAM_Y_ADDRESS_COUNTER\n        self.send_data(ystart & 0xff)\n        self.send_data((ystart >> 8) & 0xff)\n\n    # initialize\n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n\n        self.reset()\n\n        self.busy()\n        self.send_command(0x12)  # SWRESET\n        self.busy()\n\n        self.send_command(0x01)  # Driver output control\n        self.send_data(0xf9)\n        self.send_data(0x00)\n        self.send_data(0x00)\n\n        self.send_command(0x11)  # data entry mode\n        self.send_data(0x03)\n\n        self.set_windows(0, 0, self.width - 1, self.height - 1)\n        self.set_cursor(0, 0)\n\n        self.send_command(0x3C)  # BorderWavefrom\n        self.send_data(0x05)\n\n        self.send_command(0x18)  # Read built-in temperature sensor\n        self.send_data(0x80)\n\n        self.send_command(0x21)  # Display update control\n        self.send_data(0x80)\n        self.send_data(0x80)\n\n        self.busy()\n\n        return 0\n\n    # turn on display\n    def ondisplay(self):\n        self.send_command(0x20)\n        self.busy()\n\n    # image converted to bytearray\n    def getbuffer(self, image):\n        img = image\n        imwidth, imheight = img.size\n        if (imwidth == self.width and imheight == self.height):\n            img = img.convert('1')\n        elif (imwidth == self.height and imheight == self.width):\n            # image has correct dimensions, but needs to be rotated\n            img = img.rotate(90, expand=True).convert('1')\n        else:\n            logger.warning(\"Wrong image dimensions: must be \" +\n                           str(self.width) + \"x\" + str(self.height))\n            # return a blank buffer\n            return [0x00] * (int(self.width/8) * self.height)\n\n        buf = bytearray(img.tobytes('raw'))\n        return buf\n\n    # display image\n    def display(self, imageblack, imagered):\n        self.send_command(0x24)\n        self.send_data2(imageblack)\n\n        self.send_command(0x26)\n        self.send_data2(imagered)\n\n        self.ondisplay()\n\n    # display white image\n    def clear(self):\n        if self.width % 8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n\n        buf = [0xff] * (int(linewidth * self.height))\n\n        self.send_command(0x24)\n        self.send_data2(buf)\n\n        self.send_command(0x26)\n        self.send_data2(buf)\n\n        self.ondisplay()\n\n    # Compatible with older version functions\n    def Clear(self):\n        self.clear()\n\n    # sleep\n    def sleep(self):\n        self.send_command(0x10)  # DEEP_SLEEP\n        self.send_data(0x01)  # check code\n\n        epdconfig.delay_ms(2000)\n        epdconfig.module_exit()\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v213inb_v4/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.2\n# * | Date        :   2022-10-29\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\nlogger = logging.getLogger(__name__)\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN  = 17\n    DC_PIN   = 25\n    CS_PIN   = 8\n    BUSY_PIN = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n        self.SPI = spidev.SpiDev()\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def spi_writebyte2(self, data):\n        self.SPI.writebytes2(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n\n        # SPI device, bus = 0, device = 0\n        self.SPI.open(0, 0)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logger.debug(\"spi end\")\n        self.SPI.close()\n\n        logger.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN])\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN  = 17\n    DC_PIN   = 25\n    CS_PIN   = 8\n    BUSY_PIN = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def spi_writebyte2(self, data):\n        for i in range(len(data)):\n            self.SPI.SYSFS_software_spi_transfer(data[i])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logger.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logger.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN])\n\n\nclass SunriseX3:\n    # Pin definition\n    RST_PIN  = 17\n    DC_PIN   = 25\n    CS_PIN   = 8\n    BUSY_PIN = 24\n    Flag     = 0\n\n    def __init__(self):\n        import spidev\n        import Hobot.GPIO\n\n        self.GPIO = Hobot.GPIO\n        self.SPI = spidev.SpiDev()\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def spi_writebyte2(self, data):\n        # for i in range(len(data)):\n        #     self.SPI.writebytes([data[i]])\n        self.SPI.xfer3(data)\n\n    def module_init(self):\n        if self.Flag == 0:\n            self.Flag = 1\n            self.GPIO.setmode(self.GPIO.BCM)\n            self.GPIO.setwarnings(False)\n            self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n            self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n            self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n            self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n\n            # SPI device, bus = 0, device = 0\n            self.SPI.open(2, 0)\n            self.SPI.max_speed_hz = 4000000\n            self.SPI.mode = 0b00\n            return 0\n        else:\n            return 0\n\n    def module_exit(self):\n        logger.debug(\"spi end\")\n        self.SPI.close()\n\n        logger.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.Flag = 0\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN])\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelif os.path.exists('/sys/bus/platform/drivers/gpio-x3'):\n    implementation = SunriseX3()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n### END OF FILE ###"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v27inch/__init__.py",
    "content": ""
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v27inch/epd2in7.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in7.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport logging\nfrom . import epdconfig\n\n# Display resolution\nEPD_WIDTH       = 176\nEPD_HEIGHT      = 264\n\nGRAY1  = 0xff #white\nGRAY2  = 0xC0\nGRAY3  = 0x80 #gray\nGRAY4  = 0x00 #Blackest\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n        self.GRAY1  = GRAY1 #white\n        self.GRAY2  = GRAY2\n        self.GRAY3  = GRAY3 #gray\n        self.GRAY4  = GRAY4 #Blackest\n\n    lut_vcom_dc = [0x00, 0x00,\n        0x00, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x60, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x00, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x00, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n    ]\n    lut_ww = [\n        0x40, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x40, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    lut_bw = [\n        0x40, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x40, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    lut_bb = [\n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    lut_wb = [\n        0x80, 0x08, 0x00, 0x00, 0x00, 0x02,\n        0x90, 0x28, 0x28, 0x00, 0x00, 0x01,\n        0x80, 0x14, 0x00, 0x00, 0x00, 0x01,\n        0x50, 0x12, 0x12, 0x00, 0x00, 0x01,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    ###################full screen update LUT######################\n    #0~3 gray\n    gray_lut_vcom = [\n    0x00, 0x00,\n    0x00, 0x0A, 0x00, 0x00, 0x00, 0x01,\n    0x60, 0x14, 0x14, 0x00, 0x00, 0x01,\n    0x00, 0x14, 0x00, 0x00, 0x00, 0x01,\n    0x00, 0x13, 0x0A, 0x01, 0x00, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\t\t\t\t\n    ]\n    #R21\n    gray_lut_ww =[\n    0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,\n    0x90, 0x14, 0x14, 0x00, 0x00, 0x01,\n    0x10, 0x14, 0x0A, 0x00, 0x00, 0x01,\n    0xA0, 0x13, 0x01, 0x00, 0x00, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    #R22H\tr\n    gray_lut_bw =[\n    0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,\n    0x90, 0x14, 0x14, 0x00, 0x00, 0x01,\n    0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,\n    0x99, 0x0C, 0x01, 0x03, 0x04, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    #R23H\tw\n    gray_lut_wb =[\n    0x40, 0x0A, 0x00, 0x00, 0x00, 0x01,\n    0x90, 0x14, 0x14, 0x00, 0x00, 0x01,\n    0x00, 0x14, 0x0A, 0x00, 0x00, 0x01,\n    0x99, 0x0B, 0x04, 0x04, 0x01, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    #R24H\tb\n    gray_lut_bb =[\n    0x80, 0x0A, 0x00, 0x00, 0x00, 0x01,\n    0x90, 0x14, 0x14, 0x00, 0x00, 0x01,\n    0x20, 0x14, 0x0A, 0x00, 0x00, 0x01,\n    0x50, 0x13, 0x01, 0x00, 0x00, 0x01,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n    ]\n    \n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200) \n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(10)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)   \n\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n        \n    def ReadBusy(self):        \n        logging.debug(\"e-Paper busy\")\n        while(epdconfig.digital_read(self.busy_pin) == 0):      #  0: idle, 1: busy\n            epdconfig.delay_ms(200)                \n        logging.debug(\"e-Paper busy release\")\n\n    def set_lut(self):\n        self.send_command(0x20) # vcom\n        for count in range(0, 44):\n            self.send_data(self.lut_vcom_dc[count])\n        self.send_command(0x21) # ww --\n        for count in range(0, 42):\n            self.send_data(self.lut_ww[count])\n        self.send_command(0x22) # bw r\n        for count in range(0, 42):\n            self.send_data(self.lut_bw[count])\n        self.send_command(0x23) # wb w\n        for count in range(0, 42):\n            self.send_data(self.lut_bb[count])\n        self.send_command(0x24) # bb b\n        for count in range(0, 42):\n            self.send_data(self.lut_wb[count])\n            \n    def gray_SetLut(self):\n        self.send_command(0x20)\n        for count in range(0, 44):        #vcom\n            self.send_data(self.gray_lut_vcom[count])\n            \n        self.send_command(0x21)\t\t\t\t\t\t\t#red not use\n        for count in range(0, 42): \n            self.send_data(self.gray_lut_ww[count])\n\n        self.send_command(0x22)\t\t\t\t\t\t\t#bw r\n        for count in range(0, 42): \n            self.send_data(self.gray_lut_bw[count])\n\n        self.send_command(0x23)\t\t\t\t\t\t\t#wb w\n        for count in range(0, 42): \n            self.send_data(self.gray_lut_wb[count])\n\n        self.send_command(0x24)\t\t\t\t\t\t\t#bb b\n        for count in range(0, 42): \n            self.send_data(self.gray_lut_bb[count])\n\n        self.send_command(0x25)\t\t\t\t\t\t\t#vcom\n        for count in range(0, 42): \n            self.send_data(self.gray_lut_ww[count])\n    \n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n            \n        # EPD hardware init start\n        self.reset()\n        \n        self.send_command(0x01) # POWER_SETTING\n        self.send_data(0x03) # VDS_EN, VDG_EN\n        self.send_data(0x00) # VCOM_HV, VGHL_LV[1], VGHL_LV[0]\n        self.send_data(0x2b) # VDH\n        self.send_data(0x2b) # VDL\n        self.send_data(0x09) # VDHR\n        \n        self.send_command(0x06) # BOOSTER_SOFT_START\n        self.send_data(0x07)\n        self.send_data(0x07)\n        self.send_data(0x17)\n        \n        # Power optimization\n        self.send_command(0xF8)\n        self.send_data(0x60)\n        self.send_data(0xA5)\n        \n        # Power optimization\n        self.send_command(0xF8)\n        self.send_data(0x89)\n        self.send_data(0xA5)\n        \n        # Power optimization\n        self.send_command(0xF8)\n        self.send_data(0x90)\n        self.send_data(0x00)\n        \n        # Power optimization\n        self.send_command(0xF8)\n        self.send_data(0x93)\n        self.send_data(0x2A)\n        \n        # Power optimization\n        self.send_command(0xF8)\n        self.send_data(0xA0)\n        self.send_data(0xA5)\n        \n        # Power optimization\n        self.send_command(0xF8)\n        self.send_data(0xA1)\n        self.send_data(0x00)\n        \n        # Power optimization\n        self.send_command(0xF8)\n        self.send_data(0x73)\n        self.send_data(0x41)\n        \n        self.send_command(0x16) # PARTIAL_DISPLAY_REFRESH\n        self.send_data(0x00)\n        self.send_command(0x04) # POWER_ON\n        self.ReadBusy()\n\n        self.send_command(0x00) # PANEL_SETTING\n        self.send_data(0xAF) # KW-BF   KWR-AF    BWROTP 0f\n        \n        self.send_command(0x30) # PLL_CONTROL\n        self.send_data(0x3A) # 3A 100HZ   29 150Hz 39 200HZ    31 171HZ\n        \n        self.send_command(0x82) # VCM_DC_SETTING_REGISTER\n        self.send_data(0x12)\n        self.set_lut()\n        return 0\n\n    def Init_4Gray(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n        self.reset()\n        \n        self.send_command(0x01)\t\t\t#POWER SETTING\n        self.send_data (0x03)\n        self.send_data (0x00)    \n        self.send_data (0x2b)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n        self.send_data (0x2b)\t\t\n\n\n        self.send_command(0x06)         #booster soft start\n        self.send_data (0x07)\t\t#A\n        self.send_data (0x07)\t\t#B\n        self.send_data (0x17)\t\t#C \n\n        self.send_command(0xF8)         #boost??\n        self.send_data (0x60)\n        self.send_data (0xA5)\n\n        self.send_command(0xF8)         #boost??\n        self.send_data (0x89)\n        self.send_data (0xA5)\n\n        self.send_command(0xF8)         #boost??\n        self.send_data (0x90)\n        self.send_data (0x00)\n\n        self.send_command(0xF8)         #boost??\n        self.send_data (0x93)\n        self.send_data (0x2A)\n\n        self.send_command(0xF8)         #boost??\n        self.send_data (0xa0)\n        self.send_data (0xa5)\n\n        self.send_command(0xF8)         #boost??\n        self.send_data (0xa1)\n        self.send_data (0x00)\n\n        self.send_command(0xF8)         #boost??\n        self.send_data (0x73)\n        self.send_data (0x41)\n\n        self.send_command(0x16)\n        self.send_data(0x00)\t\n\n        self.send_command(0x04)\n        self.ReadBusy()\n\n        self.send_command(0x00)\t\t\t#panel setting\n        self.send_data(0xbf)\t\t#KW-BF   KWR-AF\tBWROTP 0f\n\n        self.send_command(0x30)\t\t\t#PLL setting\n        self.send_data (0x90)      \t#100hz \n\n        self.send_command(0x61)\t\t\t#resolution setting\n        self.send_data (0x00)\t\t#176\n        self.send_data (0xb0)     \t \n        self.send_data (0x01)\t\t#264\n        self.send_data (0x08)\n\n        self.send_command(0x82)\t\t\t#vcom_DC setting\n        self.send_data (0x12)\n\n        self.send_command(0X50)\t\t\t#VCOM AND DATA INTERVAL SETTING\t\t\t\n        self.send_data(0x97)\n\n    def getbuffer(self, image):\n        # logging.debug(\"bufsiz = \",int(self.width/8) * self.height)\n        buf = [0xFF] * (int(self.width/8) * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        # logging.debug(\"imwidth = %d, imheight = %d\",imwidth,imheight)\n        if(imwidth == self.width and imheight == self.height):\n            logging.debug(\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if pixels[x, y] == 0:\n                        buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))\n        elif(imwidth == self.height and imheight == self.width):\n            logging.debug(\"Horizontal\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))\n        return buf\n    \n    def getbuffer_4Gray(self, image):\n        # logging.debug(\"bufsiz = \",int(self.width/8) * self.height)\n        buf = [0xFF] * (int(self.width / 4) * self.height)\n        image_monocolor = image.convert('L')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        i=0\n        # logging.debug(\"imwidth = %d, imheight = %d\",imwidth,imheight)\n        if(imwidth == self.width and imheight == self.height):\n            logging.debug(\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if(pixels[x, y] == 0xC0):\n                        pixels[x, y] = 0x80\n                    elif (pixels[x, y] == 0x80):\n                        pixels[x, y] = 0x40\n                    i= i+1\n                    if(i%4 == 0):\n                        buf[int((x + (y * self.width))/4)] = ((pixels[x-3, y]&0xc0) | (pixels[x-2, y]&0xc0)>>2 | (pixels[x-1, y]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6)\n                        \n        elif(imwidth == self.height and imheight == self.width):\n            logging.debug(\"Horizontal\")\n            for x in range(imwidth):\n                for y in range(imheight):\n                    newx = y\n                    newy = x\n                    if(pixels[x, y] == 0xC0):\n                        pixels[x, y] = 0x80\n                    elif (pixels[x, y] == 0x80):\n                        pixels[x, y] = 0x40\n                    i= i+1\n                    if(i%4 == 0):\n                        buf[int((newx + (newy * self.width))/4)] = ((pixels[x, y-3]&0xc0) | (pixels[x, y-2]&0xc0)>>2 | (pixels[x, y-1]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6) \n        return buf\n    \n    def display(self, image):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(image[i])\n        self.send_command(0x12) \n        self.ReadBusy()\n\n    def display_4Gray(self, image):\n        self.send_command(0x10)\n        for i in range(0, 5808):                     #5808*4  46464\n            temp3=0\n            for j in range(0, 2):\n                temp1 = image[i*2+j]\n                for k in range(0, 2):\n                    temp2 = temp1&0xC0 \n                    if(temp2 == 0xC0):\n                        temp3 |= 0x01#white\n                    elif(temp2 == 0x00):\n                        temp3 |= 0x00  #black\n                    elif(temp2 == 0x80): \n                        temp3 |= 0x01  #gray1\n                    else: #0x40\n                        temp3 |= 0x00 #gray2\n                    temp3 <<= 1\t\n                    \n                    temp1 <<= 2\n                    temp2 = temp1&0xC0 \n                    if(temp2 == 0xC0):  #white\n                        temp3 |= 0x01\n                    elif(temp2 == 0x00): #black\n                        temp3 |= 0x00\n                    elif(temp2 == 0x80):\n                        temp3 |= 0x01 #gray1\n                    else :   #0x40\n                            temp3 |= 0x00\t#gray2\t\n                    if(j!=1 or k!=1):\t\t\t\t\n                        temp3 <<= 1\n                    temp1 <<= 2\n            self.send_data(temp3)\n            \n        self.send_command(0x13)\t       \n        for i in range(0, 5808):                #5808*4  46464\n            temp3=0\n            for j in range(0, 2):\n                temp1 = image[i*2+j]\n                for k in range(0, 2):\n                    temp2 = temp1&0xC0 \n                    if(temp2 == 0xC0):\n                        temp3 |= 0x01#white\n                    elif(temp2 == 0x00):\n                        temp3 |= 0x00  #black\n                    elif(temp2 == 0x80):\n                        temp3 |= 0x00  #gray1\n                    else: #0x40\n                        temp3 |= 0x01 #gray2\n                    temp3 <<= 1\t\n                    \n                    temp1 <<= 2\n                    temp2 = temp1&0xC0 \n                    if(temp2 == 0xC0):  #white\n                        temp3 |= 0x01\n                    elif(temp2 == 0x00): #black\n                        temp3 |= 0x00\n                    elif(temp2 == 0x80):\n                        temp3 |= 0x00 #gray1\n                    else:    #0x40\n                            temp3 |= 0x01\t#gray2\n                    if(j!=1 or k!=1):\t\t\t\t\t\n                        temp3 <<= 1\n                    temp1 <<= 2\n            self.send_data(temp3)\n        \n        self.gray_SetLut()\n        self.send_command(0x12)\n        epdconfig.delay_ms(200)\n        self.ReadBusy()\n        # pass\n        \n    def Clear(self, color):\n        self.send_command(0x10)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        self.send_command(0x13)\n        for i in range(0, int(self.width * self.height / 8)):\n            self.send_data(0xFF)\n        self.send_command(0x12) \n        self.ReadBusy()\n\n    def sleep(self):\n        self.send_command(0X50)\n        self.send_data(0xf7)\n        self.send_command(0X02)\n        self.send_command(0X07)\n        self.send_data(0xA5)\n        \n        epdconfig.module_exit()\n### END OF FILE ###\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v27inch/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-21\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n\n        # SPI device, bus = 0, device = 0\n        self.SPI = spidev.SpiDev(0, 0)\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.close()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v29inch/epd2in9.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in9.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V4.0\n# * | Date        :   2019-06-20\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport logging\nfrom . import epdconfig\n\n# Display resolution\nEPD_WIDTH       = 128\nEPD_HEIGHT      = 296\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n\n    lut_full_update = [\n        0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n    ]\n\n    lut_partial_update  = [\n        0x10, 0x18, 0x18, 0x08, 0x18, 0x18,\n        0x08, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n        0x00, 0x00, 0x13, 0x14, 0x44, 0x12,\n        0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n    ]\n        \n    # Hardware reset\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200) \n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(10)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(200)   \n\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n        \n    def ReadBusy(self):\n        while(epdconfig.digital_read(self.busy_pin) == 1):      #  0: idle, 1: busy\n            epdconfig.delay_ms(200) \n\n    def TurnOnDisplay(self):\n        self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2\n        self.send_data(0xC4)\n        self.send_command(0x20) # MASTER_ACTIVATION\n        self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE\n        \n        logging.debug(\"e-Paper busy\")\n        self.ReadBusy()\n        logging.debug(\"e-Paper busy release\")  \n\n    def SetWindow(self, x_start, y_start, x_end, y_end):\n        self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION\n        # x point must be the multiple of 8 or the last 3 bits will be ignored\n        self.send_data((x_start >> 3) & 0xFF)\n        self.send_data((x_end >> 3) & 0xFF)\n        self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION\n        self.send_data(y_start & 0xFF)\n        self.send_data((y_start >> 8) & 0xFF)\n        self.send_data(y_end & 0xFF)\n        self.send_data((y_end >> 8) & 0xFF)\n\n    def SetCursor(self, x, y):\n        self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER\n        # x point must be the multiple of 8 or the last 3 bits will be ignored\n        self.send_data((x >> 3) & 0xFF)\n        self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER\n        self.send_data(y & 0xFF)\n        self.send_data((y >> 8) & 0xFF)\n        self.ReadBusy()\n        \n    def init(self, lut):\n        if (epdconfig.module_init() != 0):\n            return -1\n        # EPD hardware init start\n        self.reset()\n        \n        self.send_command(0x01) # DRIVER_OUTPUT_CONTROL\n        self.send_data((EPD_HEIGHT - 1) & 0xFF)\n        self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF)\n        self.send_data(0x00) # GD = 0 SM = 0 TB = 0\n        \n        self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL \n        self.send_data(0xD7)\n        self.send_data(0xD6)\n        self.send_data(0x9D)\n        \n        self.send_command(0x2C) # WRITE_VCOM_REGISTER\n        self.send_data(0xA8) # VCOM 7C\n        \n        self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD\n        self.send_data(0x1A) # 4 dummy lines per gate\n        \n        self.send_command(0x3B) # SET_GATE_TIME\n        self.send_data(0x08) # 2us per line\n        \n        self.send_command(0x11) # DATA_ENTRY_MODE_SETTING\n        self.send_data(0x03) # X increment Y increment\n        \n        self.send_command(0x32) # WRITE_LUT_REGISTER\n        for i in range(0, len(lut)):\n            self.send_data(lut[i])\n        # EPD hardware init end\n        return 0\n\n    def getbuffer(self, image):\n        # logging.debug(\"bufsiz = \",int(self.width/8) * self.height)\n        buf = [0xFF] * (int(self.width/8) * self.height)\n        image_monocolor = image.convert('1')\n        imwidth, imheight = image_monocolor.size\n        pixels = image_monocolor.load()\n        # logging.debug(\"imwidth = %d, imheight = %d\",imwidth,imheight)\n        if(imwidth == self.width and imheight == self.height):\n            logging.debug(\"Vertical\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    # Set the bits for the column of pixels at the current position.\n                    if pixels[x, y] == 0:\n                        buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))\n        elif(imwidth == self.height and imheight == self.width):\n            logging.debug(\"Horizontal\")\n            for y in range(imheight):\n                for x in range(imwidth):\n                    newx = y\n                    newy = self.height - x - 1\n                    if pixels[x, y] == 0:\n                        buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))\n        return buf\n\n    def display(self, image):\n        if (image == None):\n            return            \n        self.SetWindow(0, 0, self.width - 1, self.height - 1)\n        for j in range(0, self.height):\n            self.SetCursor(0, j)\n            self.send_command(0x24) # WRITE_RAM\n            for i in range(0, int(self.width / 8)):\n                self.send_data(image[i + j * int(self.width / 8)])   \n        self.TurnOnDisplay()\n        \n    def Clear(self, color):\n        self.SetWindow(0, 0, self.width - 1, self.height - 1)\n        for j in range(0, self.height):\n            self.SetCursor(0, j)\n            self.send_command(0x24) # WRITE_RAM\n            for i in range(0, int(self.width / 8)):\n                self.send_data(color)   \n        self.TurnOnDisplay()\n\n    def sleep(self):\n        self.send_command(0x10) # DEEP_SLEEP_MODE\n        self.send_data(0x01)\n        \n        epdconfig.module_exit()\n### END OF FILE ###\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v29inch/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-21\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n\n        # SPI device, bus = 0, device = 0\n        self.SPI = spidev.SpiDev(0, 0)\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.close()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v3/epd2in13_V3.py",
    "content": "# *****************************************************************************\n# * | File        :\t  epd2in13_V3.py\n# * | Author      :   Waveshare team\n# * | Function    :   Electronic paper driver\n# * | Info        :\n# *----------------\n# * | This version:   V1.1\n# * | Date        :   2021-10-30\n# # | Info        :   python demo\n# -----------------------------------------------------------------------------\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n\nimport logging\nfrom . import epdconfig\nimport numpy as np\n\n# Display resolution\nEPD_WIDTH       = 122\nEPD_HEIGHT      = 250\n\nlogger = logging.getLogger(__name__)\n\nclass EPD:\n    def __init__(self):\n        self.reset_pin = epdconfig.RST_PIN\n        self.dc_pin = epdconfig.DC_PIN\n        self.busy_pin = epdconfig.BUSY_PIN\n        self.cs_pin = epdconfig.CS_PIN\n        self.width = EPD_WIDTH\n        self.height = EPD_HEIGHT\n        \n    lut_partial_update= [\n        0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x14,0x0,0x0,0x0,0x0,0x0,0x0,  \n        0x1,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x1,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,\n        0x22,0x17,0x41,0x00,0x32,0x36,\n    ]\n\n    lut_full_update = [ \n        0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0xF,0x0,0x0,0x0,0x0,0x0,0x0,\n        0xF,0x0,0x0,0xF,0x0,0x0,0x2,\n        0xF,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x1,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x0,0x0,0x0,0x0,0x0,0x0,0x0,\n        0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,\n        0x22,0x17,0x41,0x0,0x32,0x36,\n    ]\n        \n    '''\n    function :Hardware reset\n    parameter:\n    '''\n    def reset(self):\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(20) \n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(2)\n        epdconfig.digital_write(self.reset_pin, 1)\n        epdconfig.delay_ms(20)   \n\n    '''\n    function :send command\n    parameter:\n     command : Command register\n    '''\n    def send_command(self, command):\n        epdconfig.digital_write(self.dc_pin, 0)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([command])\n        epdconfig.digital_write(self.cs_pin, 1)\n\n    '''\n    function :send data\n    parameter:\n     data : Write data\n    '''\n    def send_data(self, data):\n        epdconfig.digital_write(self.dc_pin, 1)\n        epdconfig.digital_write(self.cs_pin, 0)\n        epdconfig.spi_writebyte([data])\n        epdconfig.digital_write(self.cs_pin, 1)\n    \n    '''\n    function :Wait until the busy_pin goes LOW\n    parameter:\n    '''\n    def ReadBusy(self):\n        logger.debug(\"e-Paper busy\")\n        while(epdconfig.digital_read(self.busy_pin) == 1):      # 0: idle, 1: busy\n            epdconfig.delay_ms(10)  \n        logger.debug(\"e-Paper busy release\")\n\n    '''\n    function : Turn On Display\n    parameter:\n    '''\n    def TurnOnDisplay(self):\n        self.send_command(0x22) # Display Update Control\n        self.send_data(0xC7)\n        self.send_command(0x20) # Activate Display Update Sequence\n        self.ReadBusy()\n    \n    '''\n    function : Turn On Display Part\n    parameter:\n    '''\n    def TurnOnDisplayPart(self):\n        self.send_command(0x22) # Display Update Control\n        self.send_data(0x0f)    # fast:0x0c, quality:0x0f, 0xcf\n        self.send_command(0x20) # Activate Display Update Sequence\n        self.ReadBusy()\n    \n    '''\n    function : Set lut\n    parameter:\n        lut : lut data\n    '''    \n    def Lut(self, lut):\n        self.send_command(0x32)\n        for i in range(0, 153):\n            self.send_data(lut[i])\n        self.ReadBusy()\n    \n    '''\n    function : Send lut data and configuration\n    parameter:\n        lut : lut data \n    '''\n    def SetLut(self, lut):\n        self.Lut(lut)\n        self.send_command(0x3f)\n        self.send_data(lut[153])\n        self.send_command(0x03)     # gate voltage\n        self.send_data(lut[154])\n        self.send_command(0x04)     # source voltage\n        self.send_data(lut[155])    # VSH\n        self.send_data(lut[156])    # VSH2\n        self.send_data(lut[157])    # VSL\n        self.send_command(0x2c)     # VCOM\n        self.send_data(lut[158])\n    \n    '''\n    function : Setting the display window\n    parameter:\n        xstart : X-axis starting position\n        ystart : Y-axis starting position\n        xend : End position of X-axis\n        yend : End position of Y-axis\n    '''\n    def SetWindow(self, x_start, y_start, x_end, y_end):\n        self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION\n        # x point must be the multiple of 8 or the last 3 bits will be ignored\n        self.send_data((x_start>>3) & 0xFF)\n        self.send_data((x_end>>3) & 0xFF)\n        \n        self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION\n        self.send_data(y_start & 0xFF)\n        self.send_data((y_start >> 8) & 0xFF)\n        self.send_data(y_end & 0xFF)\n        self.send_data((y_end >> 8) & 0xFF)\n\n    '''\n    function : Set Cursor\n    parameter:\n        x : X-axis starting position\n        y : Y-axis starting position\n    '''\n    def SetCursor(self, x, y):\n        self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER\n        # x point must be the multiple of 8 or the last 3 bits will be ignored\n        self.send_data(x & 0xFF)\n        \n        self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER\n        self.send_data(y & 0xFF)\n        self.send_data((y >> 8) & 0xFF)\n    \n    '''\n    function : Initialize the e-Paper register\n    parameter:\n    '''\n    def init(self):\n        if (epdconfig.module_init() != 0):\n            return -1\n        # EPD hardware init start\n        self.reset()\n        \n        self.ReadBusy()\n        self.send_command(0x12)  #SWRESET\n        self.ReadBusy() \n\n        self.send_command(0x01) #Driver output control      \n        self.send_data(0xf9)\n        self.send_data(0x00)\n        self.send_data(0x00)\n    \n        self.send_command(0x11) #data entry mode       \n        self.send_data(0x03)\n\n        self.SetWindow(0, 0, self.width-1, self.height-1)\n        self.SetCursor(0, 0)\n        \n        self.send_command(0x3c)\n        self.send_data(0x05)\n\n        self.send_command(0x21) #  Display update control\n        self.send_data(0x00)\n        self.send_data(0x80)\n    \n        self.send_command(0x18)\n        self.send_data(0x80)\n        \n        self.ReadBusy()\n        \n        self.SetLut(self.lut_full_update)\n        return 0\n\n    '''\n    function : Display images\n    parameter:\n        image : Image data\n    '''\n    def getbuffer(self, image):\n        img = image\n        imwidth, imheight = img.size\n        if(imwidth == self.width and imheight == self.height):\n            img = img.convert('1')\n        elif(imwidth == self.height and imheight == self.width):\n            # image has correct dimensions, but needs to be rotated\n            img = img.rotate(90, expand=True).convert('1')\n        else:\n            logger.warning(\"Wrong image dimensions: must be \" + str(self.width) + \"x\" + str(self.height))\n            # return a blank buffer\n            return [0x00] * (int(self.width/8) * self.height)\n\n        buf = bytearray(img.tobytes('raw'))\n        return buf\n        \n    '''\n    function : Sends the image buffer in RAM to e-Paper and displays\n    parameter:\n        image : Image data\n    '''\n    def display(self, image):\n        if self.width%8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n\n        self.send_command(0x24)\n        for j in range(0, self.height):\n            for i in range(0, linewidth):\n                self.send_data(image[i + j * linewidth])   \n        self.TurnOnDisplay()\n    \n    '''\n    function : Sends the image buffer in RAM to e-Paper and partial refresh\n    parameter:\n        image : Image data\n    '''\n    def displayPartial(self, image):\n        if self.width%8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n\n        epdconfig.digital_write(self.reset_pin, 0)\n        epdconfig.delay_ms(1)\n        epdconfig.digital_write(self.reset_pin, 1)  \n        \n        self.SetLut(self.lut_partial_update)\n        self.send_command(0x37)\n        self.send_data(0x00)\n        self.send_data(0x00)\n        self.send_data(0x00)\n        self.send_data(0x00)\n        self.send_data(0x00)\n        self.send_data(0x40)\n        self.send_data(0x00)\n        self.send_data(0x00)\n        self.send_data(0x00)  \n        self.send_data(0x00)\n\n        self.send_command(0x3C) #BorderWavefrom\n        self.send_data(0x80)\n\n        self.send_command(0x22) \n        self.send_data(0xC0)\n        self.send_command(0x20)\n        self.ReadBusy()\n\n        self.SetWindow(0, 0, self.width - 1, self.height - 1)\n        self.SetCursor(0, 0)\n        \n        self.send_command(0x24) # WRITE_RAM\n        for j in range(0, self.height):\n            for i in range(0, linewidth):\n                self.send_data(image[i + j * linewidth])   \n        self.TurnOnDisplayPart()\n\n    '''\n    function : Refresh a base image\n    parameter:\n        image : Image data\n    '''\n    def displayPartBaseImage(self, image):\n        if self.width%8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n\n        self.send_command(0x24)\n        for j in range(0, self.height):\n            for i in range(0, linewidth):\n                self.send_data(image[i + j * linewidth])   \n                \n        self.send_command(0x26)\n        for j in range(0, self.height):\n            for i in range(0, linewidth):\n                self.send_data(image[i + j * linewidth])  \n        self.TurnOnDisplay()\n    \n    '''\n    function : Clear screen\n    parameter:\n    '''\n    def Clear(self, color):\n        if self.width%8 == 0:\n            linewidth = int(self.width/8)\n        else:\n            linewidth = int(self.width/8) + 1\n        # logger.debug(linewidth)\n        \n        self.send_command(0x24)\n        for j in range(0, self.height):\n            for i in range(0, linewidth):\n                self.send_data(color)\n                \n        self.TurnOnDisplay()\n\n    '''\n    function : Enter sleep mode\n    parameter:\n    '''\n    def sleep(self):\n        self.send_command(0x10) #enter deep sleep\n        self.send_data(0x01)\n        \n        epdconfig.delay_ms(2000)\n        epdconfig.module_exit()\n\n### END OF FILE ###\n\n"
  },
  {
    "path": "pwnagotchi/ui/hw/libs/waveshare/v3/epdconfig.py",
    "content": "# /*****************************************************************************\n# * | File        :\t  epdconfig.py\n# * | Author      :   Waveshare team\n# * | Function    :   Hardware underlying interface\n# * | Info        :\n# *----------------\n# * | This version:   V1.0\n# * | Date        :   2019-06-21\n# * | Info        :   \n# ******************************************************************************\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documnetation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to  whom the Software is\n# furished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\nimport os\nimport logging\nimport sys\nimport time\n\n\nclass RaspberryPi:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import spidev\n        import RPi.GPIO\n\n        self.GPIO = RPi.GPIO\n\n        # SPI device, bus = 0, device = 0\n        self.SPI = spidev.SpiDev(0, 0)\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(pin)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.writebytes(data)\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.max_speed_hz = 4000000\n        self.SPI.mode = 0b00\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.close()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nclass JetsonNano:\n    # Pin definition\n    RST_PIN         = 17\n    DC_PIN          = 25\n    CS_PIN          = 8\n    BUSY_PIN        = 24\n\n    def __init__(self):\n        import ctypes\n        find_dirs = [\n            os.path.dirname(os.path.realpath(__file__)),\n            '/usr/local/lib',\n            '/usr/lib',\n        ]\n        self.SPI = None\n        for find_dir in find_dirs:\n            so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')\n            if os.path.exists(so_filename):\n                self.SPI = ctypes.cdll.LoadLibrary(so_filename)\n                break\n        if self.SPI is None:\n            raise RuntimeError('Cannot find sysfs_software_spi.so')\n\n        import Jetson.GPIO\n        self.GPIO = Jetson.GPIO\n\n    def digital_write(self, pin, value):\n        self.GPIO.output(pin, value)\n\n    def digital_read(self, pin):\n        return self.GPIO.input(self.BUSY_PIN)\n\n    def delay_ms(self, delaytime):\n        time.sleep(delaytime / 1000.0)\n\n    def spi_writebyte(self, data):\n        self.SPI.SYSFS_software_spi_transfer(data[0])\n\n    def module_init(self):\n        self.GPIO.setmode(self.GPIO.BCM)\n        self.GPIO.setwarnings(False)\n        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)\n        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)\n        self.SPI.SYSFS_software_spi_begin()\n        return 0\n\n    def module_exit(self):\n        logging.debug(\"spi end\")\n        self.SPI.SYSFS_software_spi_end()\n\n        logging.debug(\"close 5V, Module enters 0 power consumption ...\")\n        self.GPIO.output(self.RST_PIN, 0)\n        self.GPIO.output(self.DC_PIN, 0)\n\n        self.GPIO.cleanup()\n\n\nif os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):\n    implementation = RaspberryPi()\nelse:\n    implementation = JetsonNano()\n\nfor func in [x for x in dir(implementation) if not x.startswith('_')]:\n    setattr(sys.modules[__name__], func, getattr(implementation, func))\n\n\n### END OF FILE ###\n"
  },
  {
    "path": "pwnagotchi/ui/hw/oledhat.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass OledHat(DisplayImpl):\n    def __init__(self, config):\n        super(OledHat, self).__init__(config, 'oledhat')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(8, 8, 8, 10, 10, 8)\n        self._layout['width'] = 128\n        self._layout['height'] = 64\n        self._layout['face'] = (0, 30)\n        self._layout['name'] = (0, 10)\n        self._layout['channel'] = (72, 10)\n        self._layout['aps'] = (0, 0)\n        self._layout['uptime'] = (87, 0)\n        self._layout['line1'] = [0, 9, 128, 9]\n        self._layout['line2'] = [0, 54, 128, 54]\n        self._layout['friend_face'] = (0, 41)\n        self._layout['friend_name'] = (40, 43)\n        self._layout['shakes'] = (0, 55)\n        self._layout['mode'] = (107, 10)\n        self._layout['status'] = {\n            'pos': (37, 19),\n            'font': fonts.status_font(fonts.Small),\n            'max': 18\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing oledhat display\")\n        from pwnagotchi.ui.hw.libs.waveshare.oledhat.epd import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear()\n\n    def render(self, canvas):\n        self._display.display(canvas)\n\n    def clear(self):\n        self._display.clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/papirus.py",
    "content": "import logging\nimport os\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Papirus(DisplayImpl):\n    def __init__(self, config):\n        super(Papirus, self).__init__(config, 'papirus')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 8, 10, 23, 25, 9)\n        self._layout['width'] = 200\n        self._layout['height'] = 96\n        self._layout['face'] = (0, 24)\n        self._layout['name'] = (5, 14)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (25, 0)\n        self._layout['uptime'] = (135, 0)\n        self._layout['line1'] = [0, 11, 200, 11]\n        self._layout['line2'] = [0, 85, 200, 85]\n        self._layout['friend_face'] = (0, 69)\n        self._layout['friend_name'] = (40, 71)\n        self._layout['shakes'] = (0, 86)\n        self._layout['mode'] = (175, 86)\n        self._layout['status'] = {\n            'pos': (85, 14),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 16\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing papirus display\")\n        from pwnagotchi.ui.hw.libs.papirus.epd import EPD\n        os.environ['EPD_SIZE'] = '2.0'\n        self._display = EPD()\n        self._display.clear()\n\n    def render(self, canvas):\n        self._display.display(canvas)\n        self._display.partial_update()\n\n    def clear(self):\n        self._display.clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/spotpear24inch.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\nimport os,time\n\nclass Spotpear24inch(DisplayImpl):\n    def __init__(self, config):\n        super(Spotpear24inch, self).__init__(config, 'spotpear24inch')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(12, 10, 12, 70, 25, 9)\n        self._layout['width'] = 320\n        self._layout['height'] = 240\n        self._layout['face'] = (35, 50)\n        self._layout['name'] = (5, 20)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (40, 0)\n        self._layout['uptime'] = (240, 0)\n        self._layout['line1'] = [0, 14, 320, 14]\n        self._layout['line2'] = [0, 220, 320, 220]\n        self._layout['friend_face'] = (0, 130)\n        self._layout['friend_name'] = (40, 135)\n        self._layout['shakes'] = (0, 220)\n        self._layout['mode'] = (280, 220)\n        self._layout['status'] = {\n            'pos': (80, 160),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 20\n        }\n\n        return self._layout\n\n    def refresh(self):\n        time.sleep(0.1)\n\n    def initialize(self):\n        from pwnagotchi.ui.hw.libs.fb import fb\n        self._display = fb\n        logging.info(\"initializing spotpear 24inch lcd display\")\n        self._display.ready_fb(i=1)\n        self._display.black_scr()\n\n    def render(self, canvas):\n        self._display.show_img(canvas.rotate(180))\n        self.refresh()\n\n    def clear(self):\n        self._display.black_scr()\n        self.refresh()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare1.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass WaveshareV1(DisplayImpl):\n    def __init__(self, config):\n        super(WaveshareV1, self).__init__(config, 'waveshare_1')\n        self._display = None\n\n    def layout(self):\n        if self.config['color'] == 'black':\n            fonts.setup(10, 9, 10, 35, 25, 9)\n            self._layout['width'] = 250\n            self._layout['height'] = 122\n            self._layout['face'] = (0, 40)\n            self._layout['name'] = (5, 20)\n            self._layout['channel'] = (0, 0)\n            self._layout['aps'] = (28, 0)\n            self._layout['uptime'] = (185, 0)\n            self._layout['line1'] = [0, 14, 250, 14]\n            self._layout['line2'] = [0, 108, 250, 108]\n            self._layout['friend_face'] = (0, 92)\n            self._layout['friend_name'] = (40, 94)\n            self._layout['shakes'] = (0, 109)\n            self._layout['mode'] = (225, 109)\n            self._layout['status'] = {\n                'pos': (125, 20),\n                'font': fonts.status_font(fonts.Medium),\n                'max': 20\n            }\n        else:\n            fonts.setup(10, 8, 10, 25, 25, 9)\n            self._layout['width'] = 212\n            self._layout['height'] = 104\n            self._layout['face'] = (0, 26)\n            self._layout['name'] = (5, 15)\n            self._layout['channel'] = (0, 0)\n            self._layout['aps'] = (28, 0)\n            self._layout['uptime'] = (147, 0)\n            self._layout['line1'] = [0, 12, 212, 12]\n            self._layout['line2'] = [0, 92, 212, 92]\n            self._layout['friend_face'] = (0, 76)\n            self._layout['friend_name'] = (40, 78)\n            self._layout['shakes'] = (0, 93)\n            self._layout['mode'] = (187, 93)\n            self._layout['status'] = {\n                'pos': (91, 15),\n                'font': fonts.status_font(fonts.Medium),\n                'max': 20\n            }\n        return self._layout\n\n    def initialize(self):\n        if self.config['color'] == 'black':\n            logging.info(\"initializing waveshare v1 display in monochromatic mode\")\n            from pwnagotchi.ui.hw.libs.waveshare.v1.epd2in13 import EPD\n            self._display = EPD()\n            self._display.init(self._display.lut_full_update)\n            self._display.Clear(0xFF)\n            self._display.init(self._display.lut_partial_update)\n        elif self.config['color'] == 'fastAndFurious':\n            logging.info(\"initializing waveshare v1 3-color display in FAST MODE\")\n            logging.info(\"THIS MAY BE POTENTIALLY DANGEROUS. NO WARRANTY IS PROVIDED\")\n            logging.info(\"USE THIS DISPLAY IN THIS MODE AT YOUR OWN RISK\")\n            from pwnagotchi.ui.hw.libs.waveshare.v1.epd2in13bcFAST import EPD\n            self._display = EPD()\n            self._display.init()\n            self._display.Clear()\n        else:\n            logging.info(\"initializing waveshare v1 display 3-color mode\")\n            from pwnagotchi.ui.hw.libs.waveshare.v1.epd2in13bc import EPD\n            self._display = EPD()\n            self._display.init()\n            self._display.Clear()\n\n    def render(self, canvas):\n        if self.config['color'] == 'black':\n            buf = self._display.getbuffer(canvas)\n            self._display.display(buf)\n        elif self.config['color'] == 'fastAndFurious':\n            buf_black = self._display.getbuffer(canvas)\n            self._display.DisplayPartial(buf_black)\n        else:\n            buf_black = self._display.getbuffer(canvas)\n            self._display.displayBlack(buf_black)\n\n    def clear(self):\n        self._display.Clear(0xff)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare144lcd.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Waveshare144lcd(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare144lcd, self).__init__(config, 'waveshare144lcd')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 8, 10, 18, 25, 9)\n        self._layout['width'] = 128\n        self._layout['height'] = 128\n        self._layout['face'] = (0, 43)\n        self._layout['name'] = (0, 14)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (0, 71)\n        self._layout['uptime'] = (0, 25)\n        self._layout['line1'] = [0, 12, 127, 12]\n        self._layout['line2'] = [0, 116, 127, 116]\n        self._layout['friend_face'] = (12, 88)\n        self._layout['friend_name'] = (1, 103)\n        self._layout['shakes'] = (26, 117)\n        self._layout['mode'] = (0, 117)\n        self._layout['status'] = {\n            'pos': (65, 26),\n            'font': fonts.status_font(fonts.Small),\n            'max': 12\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare 1.44 inch lcd display\")\n        from pwnagotchi.ui.hw.libs.waveshare.lcdhat144.epd import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.clear()\n\n    def render(self, canvas):\n        self._display.display(canvas)\n\n    def clear(self):\n        pass\n        #self._display.clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare154inch.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Waveshare154inch(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare154inch, self).__init__(config, 'waveshare_1_54inch')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 9, 10, 35, 25, 9)\n        self._layout['width'] = 200\n        self._layout['height'] = 200\n        self._layout['face'] = (0, 40)\n        self._layout['name'] = (5, 20)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (28, 0)\n        self._layout['uptime'] = (135, 0)\n        self._layout['line1'] = [0, 14, 200, 14]\n        self._layout['line2'] = [0, 186, 200, 186]\n        self._layout['friend_face'] = (0, 92)\n        self._layout['friend_name'] = (40, 94)\n        self._layout['shakes'] = (0, 187)\n        self._layout['mode'] = (170, 187)\n        self._layout['status'] = {\n            'pos': (5, 90),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 20\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare v154 display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v154inch.epd1in54b import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear()\n\n    def render(self, canvas):\n        buf = self._display.getbuffer(canvas)\n        self._display.display(buf, None)\n\n    def clear(self):\n        pass\n        #self._display.Clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare2.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass WaveshareV2(DisplayImpl):\n    def __init__(self, config):\n        super(WaveshareV2, self).__init__(config, 'waveshare_2')\n        self._display = None\n\n    def layout(self):\n        if self.config['color'] == 'black':\n            fonts.setup(10, 9, 10, 35, 25, 9)\n            self._layout['width'] = 250\n            self._layout['height'] = 122\n            self._layout['face'] = (0, 40)\n            self._layout['name'] = (5, 20)\n            self._layout['channel'] = (0, 0)\n            self._layout['aps'] = (28, 0)\n            self._layout['uptime'] = (185, 0)\n            self._layout['line1'] = [0, 14, 250, 14]\n            self._layout['line2'] = [0, 108, 250, 108]\n            self._layout['friend_face'] = (0, 92)\n            self._layout['friend_name'] = (40, 94)\n            self._layout['shakes'] = (0, 109)\n            self._layout['mode'] = (225, 109)\n            self._layout['status'] = {\n                'pos': (125, 20),\n                'font': fonts.status_font(fonts.Medium),\n                'max': 20\n            }\n        else:\n            fonts.setup(10, 8, 10, 25, 25, 9)\n            self._layout['width'] = 212\n            self._layout['height'] = 104\n            self._layout['face'] = (0, 26)\n            self._layout['name'] = (5, 15)\n            self._layout['channel'] = (0, 0)\n            self._layout['aps'] = (28, 0)\n            self._layout['status'] = (91, 15)\n            self._layout['uptime'] = (147, 0)\n            self._layout['line1'] = [0, 12, 212, 12]\n            self._layout['line2'] = [0, 92, 212, 92]\n            self._layout['friend_face'] = (0, 76)\n            self._layout['friend_name'] = (40, 78)\n            self._layout['shakes'] = (0, 93)\n            self._layout['mode'] = (187, 93)\n            self._layout['status'] = {\n                'pos': (125, 20),\n                'font': fonts.status_font(fonts.Medium),\n                'max': 14\n            }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare v2 display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v2.waveshare import EPD\n        self._display = EPD()\n        self._display.init(self._display.FULL_UPDATE)\n        self._display.Clear(0xff)\n        self._display.init(self._display.PART_UPDATE)\n\n    def render(self, canvas):\n        buf = self._display.getbuffer(canvas)\n        self._display.displayPartial(buf)\n\n    def clear(self):\n        self._display.Clear(0xff)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare213bc.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Waveshare213bc(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare213bc, self).__init__(config, 'waveshare213bc')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 8, 10, 25, 25, 9)\n        self._layout['width'] = 212\n        self._layout['height'] = 104\n        self._layout['face'] = (0, 26)\n        self._layout['name'] = (5, 15)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (28, 0)\n        self._layout['uptime'] = (147, 0)\n        self._layout['line1'] = [0, 12, 212, 12]\n        self._layout['line2'] = [0, 92, 212, 92]\n        self._layout['friend_face'] = (0, 76)\n        self._layout['friend_name'] = (40, 78)\n        self._layout['shakes'] = (0, 93)\n        self._layout['mode'] = (187, 93)\n        self._layout['status'] = {\n            'pos': (91, 15),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 20\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare 213bc display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v213bc.epd2in13bc import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear()\n\n    def render(self, canvas):\n        buf = self._display.getbuffer(canvas)\n        self._display.pwndisplay(buf)\n\n    def clear(self):\n        #pass\n        self._display.pwnclear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare213d.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Waveshare213d(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare213d, self).__init__(config, 'waveshare213d')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 8, 10, 25, 25, 9)\n        self._layout['width'] = 212\n        self._layout['height'] = 104\n        self._layout['face'] = (0, 26)\n        self._layout['name'] = (5, 15)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (28, 0)\n        self._layout['uptime'] = (147, 0)\n        self._layout['line1'] = [0, 12, 212, 12]\n        self._layout['line2'] = [0, 92, 212, 92]\n        self._layout['friend_face'] = (0, 76)\n        self._layout['friend_name'] = (40, 78)\n        self._layout['shakes'] = (0, 93)\n        self._layout['mode'] = (187, 93)\n        self._layout['status'] = {\n            'pos': (91, 15),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 20\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare 213d display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v213d.epd2in13d import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear()\n\n    def render(self, canvas):\n        buf = self._display.getbuffer(canvas)\n        self._display.display(buf)\n\n    def clear(self):\n        #pass\n        self._display.Clear()\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare213inb_v4.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\nfrom PIL import Image\n\nclass Waveshare213bV4(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare213bV4, self).__init__(config, 'waveshare213inb_v4')\n        self._display = None\n\n    def layout(self):\n        if self.config['color'] == 'black':\n            fonts.setup(10, 9, 10, 35, 25, 9)\n            self._layout['width'] = 250\n            self._layout['height'] = 122\n            self._layout['face'] = (0, 40)\n            self._layout['name'] = (5, 20)\n            self._layout['channel'] = (0, 0)\n            self._layout['aps'] = (28, 0)\n            self._layout['uptime'] = (185, 0)\n            self._layout['line1'] = [0, 14, 250, 14]\n            self._layout['line2'] = [0, 108, 250, 108]\n            self._layout['friend_face'] = (0, 92)\n            self._layout['friend_name'] = (40, 94)\n            self._layout['shakes'] = (0, 109)\n            self._layout['mode'] = (225, 109)\n            self._layout['status'] = {\n                'pos': (125, 20),\n                'font': fonts.status_font(fonts.Medium),\n                'max': 20\n            }\n        else:\n            fonts.setup(10, 8, 10, 25, 25, 9)\n            self._layout['width'] = 212\n            self._layout['height'] = 104\n            self._layout['face'] = (0, 26)\n            self._layout['name'] = (5, 15)\n            self._layout['channel'] = (0, 0)\n            self._layout['aps'] = (28, 0)\n            self._layout['status'] = (91, 15)\n            self._layout['uptime'] = (147, 0)\n            self._layout['line1'] = [0, 12, 212, 12]\n            self._layout['line2'] = [0, 92, 212, 92]\n            self._layout['friend_face'] = (0, 76)\n            self._layout['friend_name'] = (40, 78)\n            self._layout['shakes'] = (0, 93)\n            self._layout['mode'] = (187, 93)\n            self._layout['status'] = {\n                'pos': (125, 20),\n                'font': fonts.status_font(fonts.Medium),\n                'max': 14\n            }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare 2.13inb v4 display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v213inb_v4.epd2in13b_V4 import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear()\n\n    def render(self, canvasBlack = None, canvasRed = None):\n        buffer = self._display.getbuffer\n        image = Image.new('1', (self._layout['height'], self._layout['width']))\n        imageBlack = image if canvasBlack is None else canvasBlack\n        imageRed = image if canvasRed is None else canvasRed\n        self._display.display(buffer(imageBlack), buffer(imageRed))\n\n    def clear(self):\n        self._display.Clear()"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare27inch.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Waveshare27inch(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare27inch, self).__init__(config, 'waveshare27inch')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 9, 10, 35, 25, 9)\n        self._layout['width'] = 264\n        self._layout['height'] = 176\n        self._layout['face'] = (66, 27)\n        self._layout['name'] = (5, 73)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (28, 0)\n        self._layout['uptime'] = (199, 0)\n        self._layout['line1'] = [0, 14, 264, 14]\n        self._layout['line2'] = [0, 162, 264, 162]\n        self._layout['friend_face'] = (0, 146)\n        self._layout['friend_name'] = (40, 146)\n        self._layout['shakes'] = (0, 163)\n        self._layout['mode'] = (239, 163)\n        self._layout['status'] = {\n            'pos': (38, 93),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 40\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare v1 2.7 inch display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v27inch.epd2in7 import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear(0xFF)\n\n    def render(self, canvas):\n        buf = self._display.getbuffer(canvas)\n        self._display.display(buf)\n\n    def clear(self):\n        self._display.Clear(0xff)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare29inch.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass Waveshare29inch(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare29inch, self).__init__(config, 'waveshare_29inch')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 9, 10, 35, 25, 9)\n        self._layout['width'] = 296\n        self._layout['height'] = 128\n        self._layout['face'] = (0, 40)\n        self._layout['name'] = (5, 25)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (28, 0)\n        self._layout['uptime'] = (230, 0)\n        self._layout['line1'] = [0, 14, 296, 14]\n        self._layout['line2'] = [0, 112, 296, 112]\n        self._layout['friend_face'] = (0, 96)\n        self._layout['friend_name'] = (40, 96)\n        self._layout['shakes'] = (0, 114)\n        self._layout['mode'] = (268, 114)\n        self._layout['status'] = {\n            'pos': (130, 25),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 28\n        }\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare v1 2.9 inch display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v29inch.epd2in9 import EPD\n        self._display = EPD()\n        self._display.init(self._display.lut_full_update)\n        self._display.Clear(0xFF)\n        self._display.init(self._display.lut_partial_update)\n\n    def render(self, canvas):\n        buf = self._display.getbuffer(canvas)\n        self._display.display(buf)\n\n    def clear(self):\n        self._display.Clear(0xFF)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare3.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\n\nclass WaveshareV3(DisplayImpl):\n    def __init__(self, config):\n        super(WaveshareV3, self).__init__(config, 'waveshare_3')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(10, 8, 10, 35, 25, 9)\n        self._layout['width'] = 250\n        self._layout['height'] = 122\n        self._layout['face'] = (0, 40)\n        self._layout['name'] = (5, 20)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (28, 0)\n        self._layout['uptime'] = (185, 0)\n        self._layout['line1'] = [0, 14, 250, 14]\n        self._layout['line2'] = [0, 108, 250, 108]\n        self._layout['friend_face'] = (0, 92)\n        self._layout['friend_name'] = (40, 94)\n        self._layout['shakes'] = (0, 109)\n        self._layout['mode'] = (225, 109)\n        self._layout['status'] = {\n            'pos': (125, 20),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 20\n        }\n\n        return self._layout\n\n    def initialize(self):\n        logging.info(\"initializing waveshare v3 display\")\n        from pwnagotchi.ui.hw.libs.waveshare.v3.epd2in13_V3 import EPD\n        self._display = EPD()\n        self._display.init()\n        self._display.Clear(0xFF)\n\n    def render(self, canvas):\n        buf = self._display.getbuffer(canvas)\n        self._display.displayPartial(buf)\n\n    def clear(self):\n        #pass\n        self._display.Clear(0xFF)\n"
  },
  {
    "path": "pwnagotchi/ui/hw/waveshare35lcd.py",
    "content": "import logging\n\nimport pwnagotchi.ui.fonts as fonts\nfrom pwnagotchi.ui.hw.base import DisplayImpl\n\nimport os,time\n\nclass Waveshare35lcd(DisplayImpl):\n    def __init__(self, config):\n        super(Waveshare35lcd, self).__init__(config, 'waveshare35lcd')\n        self._display = None\n\n    def layout(self):\n        fonts.setup(12, 10, 12, 70, 25, 9)\n        self._layout['width'] = 480\n        self._layout['height'] = 320\n        self._layout['face'] = (110, 60)\n        self._layout['name'] = (10, 30)\n        self._layout['channel'] = (0, 0)\n        self._layout['aps'] = (80, 0)\n        self._layout['uptime'] = (400, 0)\n        self._layout['line1'] = [0, 14, 480, 14]\n        self._layout['line2'] = [0,300, 480, 300]\n        self._layout['friend_face'] = (0, 220)\n        self._layout['friend_name'] = (50, 225)\n        self._layout['shakes'] = (10, 300)\n        self._layout['mode'] = (440, 300)\n        self._layout['status'] = {\n            'pos': (80, 180),\n            'font': fonts.status_font(fonts.Medium),\n            'max': 100\n        }\n\n        return self._layout\n\n    def refresh(self):\n        time.sleep(0.1)\n\n    def initialize(self):\n        from pwnagotchi.ui.hw.libs.fb import fb\n        self._display = fb\n        logging.info(\"initializing waveshare 3,5inch lcd display\")\n        self._display.ready_fb(i=1)\n        self._display.black_scr()\n\n    def render(self, canvas):\n        self._display.show_img(canvas.rotate(0))\n        self.refresh()\n\n    def clear(self):\n        self._display.black_scr()\n        self.refresh()\n"
  },
  {
    "path": "pwnagotchi/ui/state.py",
    "content": "from threading import Lock\n\n\nclass State(object):\n    def __init__(self, state={}):\n        self._state = state\n        self._lock = Lock()\n        self._listeners = {}\n        self._changes = {}\n\n    def add_element(self, key, elem):\n        self._state[key] = elem\n        self._changes[key] = True\n\n    def has_element(self, key):\n        return key in self._state\n\n    def remove_element(self, key):\n        del self._state[key]\n        self._changes[key] = True\n\n    def add_listener(self, key, cb):\n        with self._lock:\n            self._listeners[key] = cb\n\n    def items(self):\n        with self._lock:\n            return self._state.items()\n\n    def get(self, key):\n        with self._lock:\n            return self._state[key].value if key in self._state else None\n\n    def reset(self):\n        with self._lock:\n            self._changes = {}\n\n    def changes(self, ignore=()):\n        with self._lock:\n            changes = []\n            for change in self._changes.keys():\n                if change not in ignore:\n                    changes.append(change)\n            return changes\n\n    def has_changes(self):\n        with self._lock:\n            return len(self._changes) > 0\n\n    def set(self, key, value):\n        with self._lock:\n            if key in self._state:\n                prev = self._state[key].value\n                self._state[key].value = value\n\n                if prev != value:\n                    self._changes[key] = True\n                    if key in self._listeners and self._listeners[key] is not None:\n                        self._listeners[key](prev, value)\n"
  },
  {
    "path": "pwnagotchi/ui/view.py",
    "content": "import _thread\nimport logging\nimport random\nimport time\nfrom threading import Lock\n\nfrom PIL import ImageDraw\n\nimport pwnagotchi\nimport pwnagotchi.plugins as plugins\nimport pwnagotchi.ui.faces as faces\nimport pwnagotchi.ui.fonts as fonts\nimport pwnagotchi.ui.web as web\nimport pwnagotchi.utils as utils\nfrom pwnagotchi.ui.components import *\nfrom pwnagotchi.ui.state import State\nfrom pwnagotchi.voice import Voice\n\nWHITE = 0xff\nBLACK = 0x00\nROOT = None\n\n\nclass View(object):\n    def __init__(self, config, impl, state=None):\n        global ROOT\n\n        # setup faces from the configuration in case the user customized them\n        faces.load_from_config(config['ui']['faces'])\n\n        self._agent = None\n        self._render_cbs = []\n        self._config = config\n        self._canvas = None\n        self._frozen = False\n        self._lock = Lock()\n        self._voice = Voice(lang=config['main']['lang'])\n        self._implementation = impl\n        self._layout = impl.layout()\n        self._width = self._layout['width']\n        self._height = self._layout['height']\n        self._state = State(state={\n            'channel': LabeledValue(color=BLACK, label='CH', value='00', position=self._layout['channel'],\n                                    label_font=fonts.Bold,\n                                    text_font=fonts.Medium),\n            'aps': LabeledValue(color=BLACK, label='APS', value='0 (00)', position=self._layout['aps'],\n                                label_font=fonts.Bold,\n                                text_font=fonts.Medium),\n\n            'uptime': LabeledValue(color=BLACK, label='UP', value='00:00:00', position=self._layout['uptime'],\n                                   label_font=fonts.Bold,\n                                   text_font=fonts.Medium),\n\n            'line1': Line(self._layout['line1'], color=BLACK),\n            'line2': Line(self._layout['line2'], color=BLACK),\n\n            'face': Text(value=faces.SLEEP, position=self._layout['face'], color=BLACK, font=fonts.Huge),\n\n            'friend_face': Text(value=None, position=self._layout['friend_face'], font=fonts.Bold, color=BLACK),\n            'friend_name': Text(value=None, position=self._layout['friend_name'], font=fonts.BoldSmall,\n                                color=BLACK),\n\n            'name': Text(value='%s>' % 'pwnagotchi', position=self._layout['name'], color=BLACK, font=fonts.Bold),\n\n            'status': Text(value=self._voice.default(),\n                           position=self._layout['status']['pos'],\n                           color=BLACK,\n                           font=self._layout['status']['font'],\n                           wrap=True,\n                           # the current maximum number of characters per line, assuming each character is 6 pixels wide\n                           max_length=self._layout['status']['max']),\n\n            'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK,\n                                   position=self._layout['shakes'], label_font=fonts.Bold,\n                                   text_font=fonts.Medium),\n            'mode': Text(value='AUTO', position=self._layout['mode'],\n                         font=fonts.Bold, color=BLACK),\n        })\n\n        if state:\n            for key, value in state.items():\n                self._state.set(key, value)\n\n        plugins.on('ui_setup', self)\n\n        if config['ui']['fps'] > 0.0:\n            _thread.start_new_thread(self._refresh_handler, ())\n            self._ignore_changes = ()\n        else:\n            logging.warning(\"ui.fps is 0, the display will only update for major changes\")\n            self._ignore_changes = ('uptime', 'name')\n\n        ROOT = self\n\n    def set_agent(self, agent):\n        self._agent = agent\n\n    def has_element(self, key):\n        self._state.has_element(key)\n\n    def add_element(self, key, elem):\n        self._state.add_element(key, elem)\n\n    def remove_element(self, key):\n        self._state.remove_element(key)\n\n    def width(self):\n        return self._width\n\n    def height(self):\n        return self._height\n\n    def on_state_change(self, key, cb):\n        self._state.add_listener(key, cb)\n\n    def on_render(self, cb):\n        if cb not in self._render_cbs:\n            self._render_cbs.append(cb)\n\n    def _refresh_handler(self):\n        delay = 1.0 / self._config['ui']['fps']\n        while True:\n            try:\n                name = self._state.get('name')\n                self.set('name', name.rstrip('█').strip() if '█' in name else (name + ' █'))\n                self.update()\n            except Exception as e:\n                logging.warning(\"non fatal error while updating view: %s\" % e)\n\n            time.sleep(delay)\n\n    def set(self, key, value):\n        self._state.set(key, value)\n\n    def get(self, key):\n        return self._state.get(key)\n\n    def on_starting(self):\n        self.set('status', self._voice.on_starting() + (\"\\n(v%s)\" % pwnagotchi.__version__))\n        self.set('face', faces.AWAKE)\n        self.update()\n\n    def on_ai_ready(self):\n        self.set('mode', '  AI')\n        self.set('face', faces.HAPPY)\n        self.set('status', self._voice.on_ai_ready())\n        self.update()\n\n    def on_manual_mode(self, last_session):\n        self.set('mode', 'MANU')\n        self.set('face', faces.SAD if (last_session.epochs > 3 and last_session.handshakes == 0) else faces.HAPPY)\n        self.set('status', self._voice.on_last_session_data(last_session))\n        self.set('epoch', \"%04d\" % last_session.epochs)\n        self.set('uptime', last_session.duration)\n        self.set('channel', '-')\n        self.set('aps', \"%d\" % last_session.associated)\n        self.set('shakes', '%d (%s)' % (last_session.handshakes, \\\n                                        utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))\n        self.set_closest_peer(last_session.last_peer, last_session.peers)\n        self.update()\n\n    def is_normal(self):\n        return self._state.get('face') not in (\n            faces.INTENSE,\n            faces.COOL,\n            faces.BORED,\n            faces.HAPPY,\n            faces.EXCITED,\n            faces.MOTIVATED,\n            faces.DEMOTIVATED,\n            faces.SMART,\n            faces.SAD,\n            faces.LONELY)\n\n    def on_keys_generation(self):\n        self.set('face', faces.AWAKE)\n        self.set('status', self._voice.on_keys_generation())\n        self.update()\n\n    def on_normal(self):\n        self.set('face', faces.AWAKE)\n        self.set('status', self._voice.on_normal())\n        self.update()\n\n    def set_closest_peer(self, peer, num_total):\n        if peer is None:\n            self.set('friend_face', None)\n            self.set('friend_name', None)\n        else:\n            # ref. https://www.metageek.com/training/resources/understanding-rssi-2.html\n            if peer.rssi >= -67:\n                num_bars = 4\n            elif peer.rssi >= -70:\n                num_bars = 3\n            elif peer.rssi >= -80:\n                num_bars = 2\n            else:\n                num_bars = 1\n\n            name = '▌' * num_bars\n            name += '│' * (4 - num_bars)\n            name += ' %s %d (%d)' % (peer.name(), peer.pwnd_run(), peer.pwnd_total())\n\n            if num_total > 1:\n                if num_total > 9000:\n                    name += ' of over 9000'\n                else:\n                    name += ' of %d' % num_total\n\n            self.set('friend_face', peer.face())\n            self.set('friend_name', name)\n        self.update()\n\n    def on_new_peer(self, peer):\n        face = ''\n        # first time they met, neutral mood\n        if peer.first_encounter():\n            face = random.choice((faces.AWAKE, faces.COOL))\n        # a good friend, positive expression\n        elif peer.is_good_friend(self._config):\n            face = random.choice((faces.MOTIVATED, faces.FRIEND, faces.HAPPY))\n        # normal friend, neutral-positive\n        else:\n            face = random.choice((faces.EXCITED, faces.HAPPY, faces.SMART))\n\n        self.set('face', face)\n        self.set('status', self._voice.on_new_peer(peer))\n        self.update()\n        time.sleep(3)\n\n    def on_lost_peer(self, peer):\n        self.set('face', faces.LONELY)\n        self.set('status', self._voice.on_lost_peer(peer))\n        self.update()\n\n    def on_free_channel(self, channel):\n        self.set('face', faces.SMART)\n        self.set('status', self._voice.on_free_channel(channel))\n        self.update()\n\n    def on_reading_logs(self, lines_so_far=0):\n        self.set('face', faces.SMART)\n        self.set('status', self._voice.on_reading_logs(lines_so_far))\n        self.update()\n\n    def wait(self, secs, sleeping=True):\n        was_normal = self.is_normal()\n        part = secs / 10.0\n\n        for step in range(0, 10):\n            # if we weren't in a normal state before going\n            # to sleep, keep that face and status on for\n            # a while, otherwise the sleep animation will\n            # always override any minor state change before it\n            if was_normal or step > 5:\n                if sleeping:\n                    if secs > 1:\n                        self.set('face', faces.SLEEP)\n                        self.set('status', self._voice.on_napping(int(secs)))\n                    else:\n                        self.set('face', faces.SLEEP2)\n                        self.set('status', self._voice.on_awakening())\n                else:\n                    self.set('status', self._voice.on_waiting(int(secs)))\n                    good_mood = self._agent.in_good_mood()\n                    if step % 2 == 0:\n                        self.set('face', faces.LOOK_R_HAPPY if good_mood else faces.LOOK_R)\n                    else:\n                        self.set('face', faces.LOOK_L_HAPPY if good_mood else faces.LOOK_L)\n\n            time.sleep(part)\n            secs -= part\n\n        self.on_normal()\n\n    def on_shutdown(self):\n        self.set('face', faces.SLEEP)\n        self.set('status', self._voice.on_shutdown())\n        self.update(force=True)\n        self._frozen = True\n\n    def on_bored(self):\n        self.set('face', faces.BORED)\n        self.set('status', self._voice.on_bored())\n        self.update()\n\n    def on_sad(self):\n        self.set('face', faces.SAD)\n        self.set('status', self._voice.on_sad())\n        self.update()\n\n    def on_angry(self):\n        self.set('face', faces.ANGRY)\n        self.set('status', self._voice.on_angry())\n        self.update()\n\n    def on_motivated(self, reward):\n        self.set('face', faces.MOTIVATED)\n        self.set('status', self._voice.on_motivated(reward))\n        self.update()\n\n    def on_demotivated(self, reward):\n        self.set('face', faces.DEMOTIVATED)\n        self.set('status', self._voice.on_demotivated(reward))\n        self.update()\n\n    def on_excited(self):\n        self.set('face', faces.EXCITED)\n        self.set('status', self._voice.on_excited())\n        self.update()\n\n    def on_assoc(self, ap):\n        self.set('face', faces.INTENSE)\n        self.set('status', self._voice.on_assoc(ap))\n        self.update()\n\n    def on_deauth(self, sta):\n        self.set('face', faces.COOL)\n        self.set('status', self._voice.on_deauth(sta))\n        self.update()\n\n    def on_miss(self, who):\n        self.set('face', faces.SAD)\n        self.set('status', self._voice.on_miss(who))\n        self.update()\n\n    def on_grateful(self):\n        self.set('face', faces.GRATEFUL)\n        self.set('status', self._voice.on_grateful())\n        self.update()\n\n    def on_lonely(self):\n        self.set('face', faces.LONELY)\n        self.set('status', self._voice.on_lonely())\n        self.update()\n\n    def on_handshakes(self, new_shakes):\n        self.set('face', faces.HAPPY)\n        self.set('status', self._voice.on_handshakes(new_shakes))\n        self.update()\n\n    def on_unread_messages(self, count, total):\n        self.set('face', faces.EXCITED)\n        self.set('status', self._voice.on_unread_messages(count, total))\n        self.update()\n        time.sleep(5.0)\n\n    def on_uploading(self, to):\n        self.set('face', random.choice((faces.UPLOAD, faces.UPLOAD1, faces.UPLOAD2)))\n        self.set('status', self._voice.on_uploading(to))\n        self.update(force=True)\n\n    def on_rebooting(self):\n        self.set('face', faces.BROKEN)\n        self.set('status', self._voice.on_rebooting())\n        self.update()\n\n    def on_custom(self, text):\n        self.set('face', faces.DEBUG)\n        self.set('status', self._voice.custom(text))\n        self.update()\n\n    def update(self, force=False, new_data={}):\n        for key, val in new_data.items():\n            self.set(key, val)\n\n        with self._lock:\n            if self._frozen:\n                return\n\n            state = self._state\n            changes = state.changes(ignore=self._ignore_changes)\n            if force or len(changes):\n                self._canvas = Image.new('1', (self._width, self._height), WHITE)\n                drawer = ImageDraw.Draw(self._canvas)\n\n                plugins.on('ui_update', self)\n\n                for key, lv in state.items():\n                    lv.draw(self._canvas, drawer)\n\n                web.update_frame(self._canvas)\n\n                for cb in self._render_cbs:\n                    cb(self._canvas)\n\n                self._state.reset()\n"
  },
  {
    "path": "pwnagotchi/ui/web/__init__.py",
    "content": "import os\nfrom threading import Lock\n\nframe_path = '/var/tmp/pwnagotchi/pwnagotchi.png'\nframe_format = 'PNG'\nframe_ctype = 'image/png'\nframe_lock = Lock()\n\n\ndef update_frame(img):\n    global frame_lock, frame_path, frame_format\n    if not os.path.exists(os.path.dirname(frame_path)):\n        os.makedirs(os.path.dirname(frame_path))\n    with frame_lock:\n        img.save(frame_path, format=frame_format)\n"
  },
  {
    "path": "pwnagotchi/ui/web/handler.py",
    "content": "import logging\nimport os\nimport base64\nimport _thread\nimport secrets\nimport json\nfrom functools import wraps\n\n# https://stackoverflow.com/questions/14888799/disable-console-messages-in-flask-server\nlogging.getLogger('werkzeug').setLevel(logging.ERROR)\nos.environ['WERKZEUG_RUN_MAIN'] = 'true'\n\nimport pwnagotchi\nimport pwnagotchi.grid as grid\nimport pwnagotchi.ui.web as web\nfrom pwnagotchi import plugins\n\nfrom flask import send_file\nfrom flask import Response\nfrom flask import request\nfrom flask import jsonify\nfrom flask import abort\nfrom flask import redirect\nfrom flask import render_template, render_template_string\n\n\nclass Handler:\n    def __init__(self, config, agent, app):\n        self._config = config\n        self._agent = agent\n        self._app = app\n\n        self._app.add_url_rule('/', 'index', self.with_auth(self.index))\n        self._app.add_url_rule('/ui', 'ui', self.with_auth(self.ui))\n\n        self._app.add_url_rule('/shutdown', 'shutdown', self.with_auth(self.shutdown), methods=['POST'])\n        self._app.add_url_rule('/reboot', 'reboot', self.with_auth(self.reboot), methods=['POST'])\n        self._app.add_url_rule('/restart', 'restart', self.with_auth(self.restart), methods=['POST'])\n\n        # inbox\n        self._app.add_url_rule('/inbox', 'inbox', self.with_auth(self.inbox))\n        self._app.add_url_rule('/inbox/profile', 'inbox_profile', self.with_auth(self.inbox_profile))\n        self._app.add_url_rule('/inbox/peers', 'inbox_peers', self.with_auth(self.inbox_peers))\n        self._app.add_url_rule('/inbox/<id>', 'show_message', self.with_auth(self.show_message))\n        self._app.add_url_rule('/inbox/<id>/<mark>', 'mark_message', self.with_auth(self.mark_message))\n        self._app.add_url_rule('/inbox/new', 'new_message', self.with_auth(self.new_message))\n        self._app.add_url_rule('/inbox/send', 'send_message', self.with_auth(self.send_message), methods=['POST'])\n\n        # plugins\n        plugins_with_auth = self.with_auth(self.plugins)\n        self._app.add_url_rule('/plugins', 'plugins', plugins_with_auth, strict_slashes=False,\n                               defaults={'name': None, 'subpath': None})\n        self._app.add_url_rule('/plugins/<name>', 'plugins', plugins_with_auth, strict_slashes=False,\n                               methods=['GET', 'POST'], defaults={'subpath': None})\n        self._app.add_url_rule('/plugins/<name>/<path:subpath>', 'plugins', plugins_with_auth, methods=['GET', 'POST'])\n\n    def _check_creds(self, u, p):\n        # trying to be timing attack safe\n        return secrets.compare_digest(u, self._config['username']) and \\\n               secrets.compare_digest(p, self._config['password'])\n\n    def with_auth(self, f):\n        @wraps(f)\n        def wrapper(*args, **kwargs):\n            auth = request.authorization\n            if not auth or not auth.username or not auth.password or not self._check_creds(auth.username,\n                                                                                           auth.password):\n                return Response('Unauthorized', 401, {'WWW-Authenticate': 'Basic realm=\"Unauthorized\"'})\n            return f(*args, **kwargs)\n\n        return wrapper\n\n    def index(self):\n        return render_template('index.html',\n                               title=pwnagotchi.name(),\n                               other_mode='AUTO' if self._agent.mode == 'manual' else 'MANU',\n                               fingerprint=self._agent.fingerprint())\n\n    def inbox(self):\n        page = request.args.get(\"p\", default=1, type=int)\n        inbox = {\n            \"pages\": 1,\n            \"records\": 0,\n            \"messages\": []\n        }\n        error = None\n\n        try:\n            if not grid.is_connected():\n                raise Exception('not connected')\n\n            inbox = grid.inbox(page, with_pager=True)\n        except Exception as e:\n            logging.exception('error while reading pwnmail inbox')\n            error = str(e)\n\n        return render_template('inbox.html',\n                               name=pwnagotchi.name(),\n                               page=page,\n                               error=error,\n                               inbox=inbox)\n\n    def inbox_profile(self):\n        data = {}\n        error = None\n\n        try:\n            data = grid.get_advertisement_data()\n        except Exception as e:\n            logging.exception('error while reading pwngrid data')\n            error = str(e)\n\n        return render_template('profile.html',\n                               name=pwnagotchi.name(),\n                               fingerprint=self._agent.fingerprint(),\n                               data=json.dumps(data, indent=2),\n                               error=error)\n\n    def inbox_peers(self):\n        peers = {}\n        error = None\n\n        try:\n            peers = grid.memory()\n        except Exception as e:\n            logging.exception('error while reading pwngrid peers')\n            error = str(e)\n\n        return render_template('peers.html',\n                               name=pwnagotchi.name(),\n                               peers=peers,\n                               error=error)\n\n    def show_message(self, id):\n        message = {}\n        error = None\n\n        try:\n            if not grid.is_connected():\n                raise Exception('not connected')\n\n            message = grid.inbox_message(id)\n            if message['data']:\n                message['data'] = base64.b64decode(message['data']).decode(\"utf-8\")\n        except Exception as e:\n            logging.exception('error while reading pwnmail message %d' % int(id))\n            error = str(e)\n\n        return render_template('message.html',\n                               name=pwnagotchi.name(),\n                               error=error,\n                               message=message)\n\n    def new_message(self):\n        to = request.args.get(\"to\", default=\"\")\n        return render_template('new_message.html', to=to)\n\n    def send_message(self):\n        to = request.form[\"to\"]\n        message = request.form[\"message\"]\n        error = None\n\n        try:\n            if not grid.is_connected():\n                raise Exception('not connected')\n\n            grid.send_message(to, message)\n        except Exception as e:\n            error = str(e)\n\n        return jsonify({\"error\": error})\n\n    def mark_message(self, id, mark):\n        if not grid.is_connected():\n            abort(200)\n\n        logging.info(\"marking message %d as %s\" % (int(id), mark))\n        grid.mark_message(id, mark)\n        return redirect(\"/inbox\")\n\n    def plugins(self, name, subpath):\n        if name is None:\n            return render_template('plugins.html', loaded=plugins.loaded, database=plugins.database)\n\n        if name == 'toggle' and request.method == 'POST':\n            checked = True if 'enabled' in request.form else False\n            return 'success' if plugins.toggle_plugin(request.form['plugin'], checked) else 'failed'\n\n        if name in plugins.loaded and plugins.loaded[name] is not None and hasattr(plugins.loaded[name], 'on_webhook'):\n            try:\n                return plugins.loaded[name].on_webhook(subpath, request)\n            except Exception:\n                abort(500)\n        else:\n            abort(404)\n\n    # serve a message and shuts down the unit\n    def shutdown(self):\n        try:\n            return render_template('status.html', title=pwnagotchi.name(), go_back_after=60,\n                                   message='Shutting down ...')\n        finally:\n            _thread.start_new_thread(pwnagotchi.shutdown, ())\n\n    # serve a message and reboot the unit\n    def reboot(self):\n          try:\n              return render_template('status.html', title=pwnagotchi.name(), go_back_after=60,\n                                     message='Rebooting ...')\n          finally:\n              _thread.start_new_thread(pwnagotchi.reboot, ())\n\n    # serve a message and restart the unit in the other mode\n    def restart(self):\n        mode = request.form['mode']\n        if mode not in ('AUTO', 'MANU'):\n            mode = 'MANU'\n\n        try:\n            return render_template('status.html', title=pwnagotchi.name(), go_back_after=30,\n                                   message='Restarting in %s mode ...' % mode)\n        finally:\n            _thread.start_new_thread(pwnagotchi.restart, (mode,))\n\n    # serve the PNG file with the display image\n    def ui(self):\n        with web.frame_lock:\n            return send_file(web.frame_path, mimetype='image/png')\n"
  },
  {
    "path": "pwnagotchi/ui/web/server.py",
    "content": "import _thread\nimport secrets\nimport logging\nimport os\n\n# https://stackoverflow.com/questions/14888799/disable-console-messages-in-flask-server\nlogging.getLogger('werkzeug').setLevel(logging.ERROR)\nos.environ['WERKZEUG_RUN_MAIN'] = 'true'\n\nfrom flask import Flask\nfrom flask_cors import CORS\nfrom flask_wtf.csrf import CSRFProtect\n\nfrom pwnagotchi.ui.web.handler import Handler\n\nclass Server:\n    def __init__(self, agent, config):\n        self._config = config['web']\n        self._enabled = self._config['enabled']\n        self._port = self._config['port']\n        self._address = self._config['address']\n        self._origin = None\n        self._agent = agent\n        if 'origin' in self._config:\n            self._origin = self._config['origin']\n\n        if self._enabled:\n            _thread.start_new_thread(self._http_serve, ())\n\n    def _http_serve(self):\n        if self._address is not None:\n            web_path = os.path.dirname(os.path.realpath(__file__))\n\n            app = Flask(__name__,\n                        static_url_path='',\n                        static_folder=os.path.join(web_path, 'static'),\n                        template_folder=os.path.join(web_path, 'templates'))\n\n            app.secret_key = secrets.token_urlsafe(256)\n\n            if self._origin:\n                CORS(app, resources={r\"*\": {\"origins\": self._origin}})\n\n            CSRFProtect(app)\n            Handler(self._config, self._agent, app)\n\n            logging.info(\"web ui available at http://%s:%d/\" % (self._address, self._port))\n\n            app.run(host=self._address, port=self._port, debug=False)\n        else:\n            logging.info(\"could not get ip of usb0, video server not starting\")\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/css/jquery.jqplot.css",
    "content": "/*rules for the plot target div.  These will be cascaded down to all plot elements according to css rules*/\r\n.jqplot-target {\r\n    position: relative;\r\n    color: #666666;\r\n    font-family: \"Trebuchet MS\", Arial, Helvetica, sans-serif;\r\n    font-size: 1em;\r\n/*    height: 300px;\r\n    width: 400px;*/\r\n}\r\n\r\n/*rules applied to all axes*/\r\n.jqplot-axis {\r\n    font-size: 0.75em;\r\n}\r\n\r\n.jqplot-xaxis {\r\n    margin-top: 10px;\r\n}\r\n\r\n.jqplot-x2axis {\r\n    margin-bottom: 10px;\r\n}\r\n\r\n.jqplot-yaxis {\r\n    margin-right: 10px;\r\n}\r\n\r\n.jqplot-y2axis, .jqplot-y3axis, .jqplot-y4axis, .jqplot-y5axis, .jqplot-y6axis, .jqplot-y7axis, .jqplot-y8axis, .jqplot-y9axis, .jqplot-yMidAxis {\r\n    margin-left: 10px;\r\n    margin-right: 10px;\r\n}\r\n\r\n/*rules applied to all axis tick divs*/\r\n.jqplot-axis-tick, .jqplot-xaxis-tick, .jqplot-yaxis-tick, .jqplot-x2axis-tick, .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick, .jqplot-yMidAxis-tick {\r\n    position: absolute;\r\n    white-space: pre;\r\n}\r\n\r\n\r\n.jqplot-xaxis-tick {\r\n    top: 0px;\r\n    /* initial position untill tick is drawn in proper place */\r\n    left: 15px;\r\n/*    padding-top: 10px;*/\r\n    vertical-align: top;\r\n}\r\n\r\n.jqplot-x2axis-tick {\r\n    bottom: 0px;\r\n    /* initial position untill tick is drawn in proper place */\r\n    left: 15px;\r\n/*    padding-bottom: 10px;*/\r\n    vertical-align: bottom;\r\n}\r\n\r\n.jqplot-yaxis-tick {\r\n    right: 0px;\r\n    /* initial position untill tick is drawn in proper place */\r\n    top: 15px;\r\n/*    padding-right: 10px;*/\r\n    text-align: right;\r\n}\r\n\r\n.jqplot-yaxis-tick.jqplot-breakTick {\r\n    right: -20px;\r\n    margin-right: 0px;\r\n    padding:1px 5px 1px 5px;\r\n    /*background-color: white;*/\r\n    z-index: 2;\r\n    font-size: 1.5em;\r\n}\r\n\r\n.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick {\r\n    left: 0px;\r\n    /* initial position untill tick is drawn in proper place */\r\n    top: 15px;\r\n/*    padding-left: 10px;*/\r\n/*    padding-right: 15px;*/\r\n    text-align: left;\r\n}\r\n\r\n.jqplot-yMidAxis-tick {\r\n    text-align: center;\r\n    white-space: nowrap;\r\n}\r\n\r\n.jqplot-xaxis-label {\r\n    margin-top: 10px;\r\n    font-size: 11pt;\r\n    position: absolute;\r\n}\r\n\r\n.jqplot-x2axis-label {\r\n    margin-bottom: 10px;\r\n    font-size: 11pt;\r\n    position: absolute;\r\n}\r\n\r\n.jqplot-yaxis-label {\r\n    margin-right: 10px;\r\n/*    text-align: center;*/\r\n    font-size: 11pt;\r\n    position: absolute;\r\n}\r\n\r\n.jqplot-yMidAxis-label {\r\n    font-size: 11pt;\r\n    position: absolute;\r\n}\r\n\r\n.jqplot-y2axis-label, .jqplot-y3axis-label, .jqplot-y4axis-label, .jqplot-y5axis-label, .jqplot-y6axis-label, .jqplot-y7axis-label, .jqplot-y8axis-label, .jqplot-y9axis-label {\r\n/*    text-align: center;*/\r\n    font-size: 11pt;\r\n    margin-left: 10px;\r\n    position: absolute;\r\n}\r\n\r\n.jqplot-meterGauge-tick {\r\n    font-size: 0.75em;\r\n    color: #999999;\r\n}\r\n\r\n.jqplot-meterGauge-label {\r\n    font-size: 1em;\r\n    color: #999999;\r\n}\r\n\r\ntable.jqplot-table-legend {\r\n    margin-top: 12px;\r\n    margin-bottom: 12px;\r\n    margin-left: 12px;\r\n    margin-right: 12px;\r\n}\r\n\r\ntable.jqplot-table-legend, table.jqplot-cursor-legend {\r\n    background-color: rgba(255,255,255,0.6);\r\n    border: 1px solid #cccccc;\r\n    position: absolute;\r\n    font-size: 0.75em;\r\n}\r\n\r\ntd.jqplot-table-legend {\r\n    vertical-align:middle;\r\n}\r\n\r\n/*\r\nThese rules could be used instead of assigning\r\nelement styles and relying on js object properties.\r\n*/\r\n\r\n/*\r\ntd.jqplot-table-legend-swatch {\r\n    padding-top: 0.5em;\r\n    text-align: center;\r\n}\r\n\r\ntr.jqplot-table-legend:first td.jqplot-table-legend-swatch {\r\n    padding-top: 0px;\r\n}\r\n*/\r\n\r\ntd.jqplot-seriesToggle:hover, td.jqplot-seriesToggle:active {\r\n    cursor: pointer;\r\n}\r\n\r\n.jqplot-table-legend .jqplot-series-hidden {\r\n    text-decoration: line-through;\r\n}\r\n\r\ndiv.jqplot-table-legend-swatch-outline {\r\n    border: 1px solid #cccccc;\r\n    padding:1px;\r\n}\r\n\r\ndiv.jqplot-table-legend-swatch {\r\n    width:0px;\r\n    height:0px;\r\n    border-top-width: 5px;\r\n    border-bottom-width: 5px;\r\n    border-left-width: 6px;\r\n    border-right-width: 6px;\r\n    border-top-style: solid;\r\n    border-bottom-style: solid;\r\n    border-left-style: solid;\r\n    border-right-style: solid;\r\n}\r\n\r\n.jqplot-title {\r\n    top: 0px;\r\n    left: 0px;\r\n    padding-bottom: 0.5em;\r\n    font-size: 1.2em;\r\n}\r\n\r\ntable.jqplot-cursor-tooltip {\r\n    border: 1px solid #cccccc;\r\n    font-size: 0.75em;\r\n}\r\n\r\n\r\n.jqplot-cursor-tooltip {\r\n    border: 1px solid #cccccc;\r\n    font-size: 0.75em;\r\n    white-space: nowrap;\r\n    background: rgba(208,208,208,0.5);\r\n    padding: 1px;\r\n}\r\n\r\n.jqplot-highlighter-tooltip, .jqplot-canvasOverlay-tooltip {\r\n    border: 1px solid #cccccc;\r\n    font-size: 0.75em;\r\n    white-space: nowrap;\r\n    background: rgba(208,208,208,0.5);\r\n    padding: 1px;\r\n}\r\n\r\n.jqplot-point-label {\r\n    font-size: 0.75em;\r\n    z-index: 2;\r\n}\r\n      \r\ntd.jqplot-cursor-legend-swatch {\r\n    vertical-align: middle;\r\n    text-align: center;\r\n}\r\n\r\ndiv.jqplot-cursor-legend-swatch {\r\n    width: 1.2em;\r\n    height: 0.7em;\r\n}\r\n\r\n.jqplot-error {\r\n/*   Styles added to the plot target container when there is an error go here.*/\r\n    text-align: center;\r\n}\r\n\r\n.jqplot-error-message {\r\n/*    Styling of the custom error message div goes here.*/\r\n    position: relative;\r\n    top: 46%;\r\n    display: inline-block;\r\n}\r\n\r\ndiv.jqplot-bubble-label {\r\n    font-size: 0.8em;\r\n/*    background: rgba(90%, 90%, 90%, 0.15);*/\r\n    padding-left: 2px;\r\n    padding-right: 2px;\r\n    color: rgb(20%, 20%, 20%);\r\n}\r\n\r\ndiv.jqplot-bubble-label.jqplot-bubble-label-highlight {\r\n    background: rgba(90%, 90%, 90%, 0.7);\r\n}\r\n\r\ndiv.jqplot-noData-container {\r\n    text-align: center;\r\n    background-color: rgba(96%, 96%, 96%, 0.3);\r\n}\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/css/style.css",
    "content": ".ui-image {\n    width: 100%;\n}\n\n.pixelated {\n    image-rendering: optimizeSpeed; /* Legal fallback */\n    image-rendering: -moz-crisp-edges; /* Firefox        */\n    image-rendering: -o-crisp-edges; /* Opera          */\n    image-rendering: -webkit-optimize-contrast; /* Safari         */\n    image-rendering: optimize-contrast; /* CSS3 Proposed  */\n    image-rendering: crisp-edges; /* CSS4 Proposed  */\n    image-rendering: pixelated; /* CSS4 Proposed  */\n    -ms-interpolation-mode: nearest-neighbor; /* IE8+           */\n}\n\n.image-wrapper {\n    flex: 1;\n    position: relative;\n}\n\ndiv.status {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n}\n\na.read {\n    color: #777 !important;\n}\n\np.messagebody {\n    padding: 1em;\n}\n\nli.navitem {\n    width: 16.66% !important;\n    clear: none !important;\n}\n\n/* Custom indentations are needed because the length of custom labels differs from\n   the length of the standard labels */\n.custom-size-flipswitch.ui-flipswitch .ui-btn.ui-flipswitch-on {\n    text-indent: -5.9em;\n}\n\n.custom-size-flipswitch.ui-flipswitch .ui-flipswitch-off {\n    text-indent: 0.5em;\n}\n\n/* Custom widths are needed because the length of custom labels differs from\n   the length of the standard labels */\n.custom-size-flipswitch.ui-flipswitch {\n    width: 8.875em;\n}\n\n.custom-size-flipswitch.ui-flipswitch.ui-flipswitch-active {\n    padding-left: 7em;\n    width: 1.875em;\n}\n\n@media (min-width: 28em) {\n    /*Repeated from rule .ui-flipswitch above*/\n    .ui-field-contain > label + .custom-size-flipswitch.ui-flipswitch {\n        width: 1.875em;\n    }\n}\n\n#container {\n    display: flex;\n    flex-wrap: wrap;\n    justify-content: space-around;\n}\n\n.plugins-box {\n    margin: 0.5rem;\n    padding: 0.2rem;\n    border-style: groove;\n    border-radius: 0.5rem;\n    background-color: lightgrey;\n    text-align: center;\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.jqplot.js",
    "content": "/**\r\n * Title: jqPlot Charts\r\n * \r\n * Pure JavaScript plotting plugin for jQuery.\r\n * \r\n * About: Version\r\n * \r\n * version: 1.0.9 \r\n * revision: d96a669\r\n * \r\n * About: Copyright & License\r\n * \r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT and GPL version 2.0 licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly.\r\n * \r\n * See <GPL Version 2> and <MIT License> contained within this distribution for further information. \r\n *\r\n * The author would appreciate an email letting him know of any substantial\r\n * use of jqPlot.  You can reach the author at: chris at jqplot dot com \r\n * or see http://www.jqplot.com/info.php.  This is, of course, not required.\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php.\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n * \r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n * \r\n * About: Introduction\r\n * \r\n * jqPlot requires jQuery (1.4+ required for certain features). jQuery 1.4.2 is included in the distribution.  \r\n * To use jqPlot include jQuery, the jqPlot jQuery plugin, the jqPlot css file and optionally \r\n * the excanvas script for IE support in your web page:\r\n * \r\n * > <!--[if lt IE 9]><script language=\"javascript\" type=\"text/javascript\" src=\"excanvas.js\"></script><![endif]-->\r\n * > <script language=\"javascript\" type=\"text/javascript\" src=\"jquery-1.4.4.min.js\"></script>\r\n * > <script language=\"javascript\" type=\"text/javascript\" src=\"jquery.jqplot.min.js\"></script>\r\n * > <link rel=\"stylesheet\" type=\"text/css\" href=\"jquery.jqplot.css\" />\r\n * \r\n * jqPlot can be customized by overriding the defaults of any of the objects which make\r\n * up the plot. The general usage of jqplot is:\r\n * \r\n * > chart = $.jqplot('targetElemId', [dataArray,...], {optionsObject});\r\n * \r\n * The options available to jqplot are detailed in <jqPlot Options> in the jqPlotOptions.txt file.\r\n * \r\n * An actual call to $.jqplot() may look like the \r\n * examples below:\r\n * \r\n * > chart = $.jqplot('chartdiv',  [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]);\r\n * \r\n * or\r\n * \r\n * > dataArray = [34,12,43,55,77];\r\n * > chart = $.jqplot('targetElemId', [dataArray, ...], {title:'My Plot', axes:{yaxis:{min:20, max:100}}});\r\n * \r\n * For more inforrmation, see <jqPlot Usage>.\r\n * \r\n * About: Usage\r\n * \r\n * See <jqPlot Usage>\r\n * \r\n * About: Available Options \r\n * \r\n * See <jqPlot Options> for a list of options available thorugh the options object (not complete yet!)\r\n * \r\n * About: Options Usage\r\n * \r\n * See <Options Tutorial>\r\n * \r\n * About: Changes\r\n * \r\n * See <Change Log>\r\n * \r\n */\r\n\r\n(function($) {\r\n    // make sure undefined is undefined\r\n    var undefined;\r\n    \r\n    $.fn.emptyForce = function() {\r\n      for ( var i = 0, elem; (elem = $(this)[i]) != null; i++ ) {\r\n        // Remove element nodes and prevent memory leaks\r\n        if ( elem.nodeType === 1 ) {\r\n          $.cleanData( elem.getElementsByTagName(\"*\") );\r\n        }\r\n  \r\n        // Remove any remaining nodes\r\n        if ($.jqplot.use_excanvas) {\r\n          elem.outerHTML = \"\";\r\n        }\r\n        else {\r\n          while ( elem.firstChild ) {\r\n            elem.removeChild( elem.firstChild );\r\n          }\r\n        }\r\n\r\n        elem = null;\r\n      }\r\n  \r\n      return $(this);\r\n    };\r\n  \r\n    $.fn.removeChildForce = function(parent) {\r\n      while ( parent.firstChild ) {\r\n        this.removeChildForce( parent.firstChild );\r\n        parent.removeChild( parent.firstChild );\r\n      }\r\n    };\r\n\r\n    $.fn.jqplot = function() {\r\n        var datas = [];\r\n        var options = [];\r\n        // see how many data arrays we have\r\n        for (var i=0, l=arguments.length; i<l; i++) {\r\n            if ($.isArray(arguments[i])) {\r\n                datas.push(arguments[i]);\r\n            }\r\n            else if ($.isPlainObject(arguments[i])) {\r\n                options.push(arguments[i]);\r\n            }\r\n        }\r\n\r\n        return this.each(function(index) {\r\n            var tid, \r\n                plot, \r\n                $this = $(this),\r\n                dl = datas.length,\r\n                ol = options.length,\r\n                data, \r\n                opts;\r\n\r\n            if (index < dl) {\r\n                data = datas[index];\r\n            }\r\n            else {\r\n                data = dl ? datas[dl-1] : null;\r\n            }\r\n\r\n            if (index < ol) {\r\n                opts = options[index];\r\n            }\r\n            else {\r\n                opts = ol ? options[ol-1] : null;\r\n            }\r\n\r\n            // does el have an id?\r\n            // if not assign it one.\r\n            tid = $this.attr('id');\r\n            if (tid === undefined) {\r\n                tid = 'jqplot_target_' + $.jqplot.targetCounter++;\r\n                $this.attr('id', tid);\r\n            }\r\n\r\n            plot = $.jqplot(tid, data, opts);\r\n\r\n            $this.data('jqplot', plot);\r\n        });\r\n    };\r\n\r\n\r\n    /**\r\n     * Namespace: $.jqplot\r\n     * jQuery function called by the user to create a plot.\r\n     *  \r\n     * Parameters:\r\n     * target - ID of target element to render the plot into.\r\n     * data - an array of data series.\r\n     * options - user defined options object.  See the individual classes for available options.\r\n     * \r\n     * Properties:\r\n     * config - object to hold configuration information for jqPlot plot object.\r\n     * \r\n     * attributes:\r\n     * enablePlugins - False to disable plugins by default.  Plugins must then be explicitly \r\n     *   enabled in the individual plot options.  Default: false.\r\n     *   This property sets the \"show\" property of certain plugins to true or false.\r\n     *   Only plugins that can be immediately active upon loading are affected.  This includes\r\n     *   non-renderer plugins like cursor, dragable, highlighter, and trendline.\r\n     * defaultHeight - Default height for plots where no css height specification exists.  This\r\n     *   is a jqplot wide default.\r\n     * defaultWidth - Default height for plots where no css height specification exists.  This\r\n     *   is a jqplot wide default.\r\n     */\r\n\r\n    $.jqplot = function(target, data, options) {\r\n        var _data = null, _options = null;\r\n\r\n        if (arguments.length === 3) {\r\n            _data = data;\r\n            _options = options;\r\n        }\r\n\r\n        else if (arguments.length === 2) {\r\n            if ($.isArray(data)) {\r\n                _data = data;\r\n            }\r\n\r\n            else if ($.isPlainObject(data)) {\r\n                _options = data;\r\n            }\r\n        }\r\n\r\n        if (_data === null && _options !== null && _options.data) {\r\n            _data = _options.data;\r\n        }\r\n\r\n        var plot = new jqPlot();\r\n        // remove any error class that may be stuck on target.\r\n        $('#'+target).removeClass('jqplot-error');\r\n        \r\n        if ($.jqplot.config.catchErrors) {\r\n            try {\r\n                plot.init(target, _data, _options);\r\n                plot.draw();\r\n                plot.themeEngine.init.call(plot);\r\n                return plot;\r\n            }\r\n            catch(e) {\r\n                var msg = $.jqplot.config.errorMessage || e.message;\r\n                $('#'+target).append('<div class=\"jqplot-error-message\">'+msg+'</div>');\r\n                $('#'+target).addClass('jqplot-error');\r\n                document.getElementById(target).style.background = $.jqplot.config.errorBackground;\r\n                document.getElementById(target).style.border = $.jqplot.config.errorBorder;\r\n                document.getElementById(target).style.fontFamily = $.jqplot.config.errorFontFamily;\r\n                document.getElementById(target).style.fontSize = $.jqplot.config.errorFontSize;\r\n                document.getElementById(target).style.fontStyle = $.jqplot.config.errorFontStyle;\r\n                document.getElementById(target).style.fontWeight = $.jqplot.config.errorFontWeight;\r\n            }\r\n        }\r\n        else {        \r\n            plot.init(target, _data, _options);\r\n            plot.draw();\r\n            plot.themeEngine.init.call(plot);\r\n            return plot;\r\n        }\r\n    };\r\n\r\n    $.jqplot.version = \"1.0.9\";\r\n    $.jqplot.revision = \"d96a669\";\r\n\r\n    $.jqplot.targetCounter = 1;\r\n\r\n    // canvas manager to reuse canvases on the plot.\r\n    // Should help solve problem of canvases not being freed and\r\n    // problem of waiting forever for firefox to decide to free memory.\r\n    $.jqplot.CanvasManager = function() {\r\n        // canvases are managed globally so that they can be reused\r\n        // across plots after they have been freed\r\n        if (typeof $.jqplot.CanvasManager.canvases == 'undefined') {\r\n            $.jqplot.CanvasManager.canvases = [];\r\n            $.jqplot.CanvasManager.free = [];\r\n        }\r\n        \r\n        var myCanvases = [];\r\n        \r\n        this.getCanvas = function() {\r\n            var canvas;\r\n            var makeNew = true;\r\n            \r\n            if (!$.jqplot.use_excanvas) {\r\n                for (var i = 0, l = $.jqplot.CanvasManager.canvases.length; i < l; i++) {\r\n                    if ($.jqplot.CanvasManager.free[i] === true) {\r\n                        makeNew = false;\r\n                        canvas = $.jqplot.CanvasManager.canvases[i];\r\n                        // $(canvas).removeClass('jqplot-canvasManager-free').addClass('jqplot-canvasManager-inuse');\r\n                        $.jqplot.CanvasManager.free[i] = false;\r\n                        myCanvases.push(i);\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            if (makeNew) {\r\n                canvas = document.createElement('canvas');\r\n                myCanvases.push($.jqplot.CanvasManager.canvases.length);\r\n                $.jqplot.CanvasManager.canvases.push(canvas);\r\n                $.jqplot.CanvasManager.free.push(false);\r\n            }   \r\n            \r\n            return canvas;\r\n        };\r\n        \r\n        // this method has to be used after settings the dimesions\r\n        // on the element returned by getCanvas()\r\n        this.initCanvas = function(canvas) {\r\n            if ($.jqplot.use_excanvas) {\r\n                return window.G_vmlCanvasManager.initElement(canvas);\r\n            }\r\n\r\n            var cctx = canvas.getContext('2d');\r\n\r\n            var canvasBackingScale = 1;\r\n            if (window.devicePixelRatio > 1 && (cctx.webkitBackingStorePixelRatio === undefined || \r\n                                                cctx.webkitBackingStorePixelRatio < 2)) {\r\n                canvasBackingScale = window.devicePixelRatio;\r\n            }\r\n            var oldWidth = canvas.width;\r\n            var oldHeight = canvas.height;\r\n\r\n            canvas.width = canvasBackingScale * canvas.width;\r\n            canvas.height = canvasBackingScale * canvas.height;\r\n            canvas.style.width = oldWidth + 'px';\r\n            canvas.style.height = oldHeight + 'px';\r\n            cctx.save();\r\n\r\n            cctx.scale(canvasBackingScale, canvasBackingScale);\r\n\r\n            return canvas;\r\n        };\r\n\r\n        this.freeAllCanvases = function() {\r\n            for (var i = 0, l=myCanvases.length; i < l; i++) {\r\n                this.freeCanvas(myCanvases[i]);\r\n            }\r\n            myCanvases = [];\r\n        };\r\n\r\n        this.freeCanvas = function(idx) {\r\n            if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {\r\n                // excanvas can't be reused, but properly unset\r\n                window.G_vmlCanvasManager.uninitElement($.jqplot.CanvasManager.canvases[idx]);\r\n                $.jqplot.CanvasManager.canvases[idx] = null;\r\n            } \r\n            else {\r\n                var canvas = $.jqplot.CanvasManager.canvases[idx];\r\n                canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);\r\n                $(canvas).unbind().removeAttr('class').removeAttr('style');\r\n                // Style attributes seemed to be still hanging around.  wierd.  Some ticks\r\n                // still retained a left: 0px attribute after reusing a canvas.\r\n                $(canvas).css({left: '', top: '', position: ''});\r\n                // setting size to 0 may save memory of unused canvases?\r\n                canvas.width = 0;\r\n                canvas.height = 0;\r\n                $.jqplot.CanvasManager.free[idx] = true;\r\n            }\r\n        };\r\n        \r\n    };\r\n\r\n            \r\n    // Convienence function that won't hang IE or FF without FireBug.\r\n    $.jqplot.log = function() {\r\n        if (window.console) {\r\n            window.console.log.apply(window.console, arguments);\r\n        }\r\n    };\r\n        \r\n    $.jqplot.config = {\r\n        addDomReference: false,\r\n        enablePlugins:false,\r\n        defaultHeight:300,\r\n        defaultWidth:400,\r\n        UTCAdjust:false,\r\n        timezoneOffset: new Date(new Date().getTimezoneOffset() * 60000),\r\n        errorMessage: '',\r\n        errorBackground: '',\r\n        errorBorder: '',\r\n        errorFontFamily: '',\r\n        errorFontSize: '',\r\n        errorFontStyle: '',\r\n        errorFontWeight: '',\r\n        catchErrors: false,\r\n        defaultTickFormatString: \"%.1f\",\r\n        defaultColors: [ \"#4bb2c5\", \"#EAA228\", \"#c5b47f\", \"#579575\", \"#839557\", \"#958c12\", \"#953579\", \"#4b5de4\", \"#d8b83f\", \"#ff5800\", \"#0085cc\", \"#c747a3\", \"#cddf54\", \"#FBD178\", \"#26B4E3\", \"#bd70c7\"],\r\n        defaultNegativeColors: [ \"#498991\", \"#C08840\", \"#9F9274\", \"#546D61\", \"#646C4A\", \"#6F6621\", \"#6E3F5F\", \"#4F64B0\", \"#A89050\", \"#C45923\", \"#187399\", \"#945381\", \"#959E5C\", \"#C7AF7B\", \"#478396\", \"#907294\"],\r\n        dashLength: 4,\r\n        gapLength: 4,\r\n        dotGapLength: 2.5,\r\n        srcLocation: 'jqplot/src/',\r\n        pluginLocation: 'jqplot/src/plugins/'\r\n    };\r\n    \r\n    \r\n    $.jqplot.arrayMax = function( array ){\r\n        return Math.max.apply( Math, array );\r\n    };\r\n    \r\n    $.jqplot.arrayMin = function( array ){\r\n        return Math.min.apply( Math, array );\r\n    };\r\n    \r\n    $.jqplot.enablePlugins = $.jqplot.config.enablePlugins;\r\n    \r\n    // canvas related tests taken from modernizer:\r\n    // Copyright (c) 2009 - 2010 Faruk Ates.\r\n    // http://www.modernizr.com\r\n    \r\n    $.jqplot.support_canvas = function() {\r\n        if (typeof $.jqplot.support_canvas.result == 'undefined') {\r\n            $.jqplot.support_canvas.result = !!document.createElement('canvas').getContext; \r\n        }\r\n        return $.jqplot.support_canvas.result;\r\n    };\r\n            \r\n    $.jqplot.support_canvas_text = function() {\r\n        if (typeof $.jqplot.support_canvas_text.result == 'undefined') {\r\n            if (window.G_vmlCanvasManager !== undefined && window.G_vmlCanvasManager._version > 887) {\r\n                $.jqplot.support_canvas_text.result = true;\r\n            }\r\n            else {\r\n                $.jqplot.support_canvas_text.result = !!(document.createElement('canvas').getContext && typeof document.createElement('canvas').getContext('2d').fillText == 'function');\r\n            }\r\n             \r\n        }\r\n        return $.jqplot.support_canvas_text.result;\r\n    };\r\n    \r\n    $.jqplot.use_excanvas = ((!$.support.boxModel || !$.support.objectAll || !$support.leadingWhitespace) && !$.jqplot.support_canvas()) ? true : false;\r\n    \r\n    /**\r\n     * \r\n     * Hooks: jqPlot Pugin Hooks\r\n     * \r\n     * $.jqplot.preInitHooks - called before initialization.\r\n     * $.jqplot.postInitHooks - called after initialization.\r\n     * $.jqplot.preParseOptionsHooks - called before user options are parsed.\r\n     * $.jqplot.postParseOptionsHooks - called after user options are parsed.\r\n     * $.jqplot.preDrawHooks - called before plot draw.\r\n     * $.jqplot.postDrawHooks - called after plot draw.\r\n     * $.jqplot.preDrawSeriesHooks - called before each series is drawn.\r\n     * $.jqplot.postDrawSeriesHooks - called after each series is drawn.\r\n     * $.jqplot.preDrawLegendHooks - called before the legend is drawn.\r\n     * $.jqplot.addLegendRowHooks - called at the end of legend draw, so plugins\r\n     *     can add rows to the legend table.\r\n     * $.jqplot.preSeriesInitHooks - called before series is initialized.\r\n     * $.jqplot.postSeriesInitHooks - called after series is initialized.\r\n     * $.jqplot.preParseSeriesOptionsHooks - called before series related options\r\n     *     are parsed.\r\n     * $.jqplot.postParseSeriesOptionsHooks - called after series related options\r\n     *     are parsed.\r\n     * $.jqplot.eventListenerHooks - called at the end of plot drawing, binds\r\n     *     listeners to the event canvas which lays on top of the grid area.\r\n     * $.jqplot.preDrawSeriesShadowHooks - called before series shadows are drawn.\r\n     * $.jqplot.postDrawSeriesShadowHooks - called after series shadows are drawn.\r\n     * \r\n     */\r\n    \r\n    $.jqplot.preInitHooks = [];\r\n    $.jqplot.postInitHooks = [];\r\n    $.jqplot.preParseOptionsHooks = [];\r\n    $.jqplot.postParseOptionsHooks = [];\r\n    $.jqplot.preDrawHooks = [];\r\n    $.jqplot.postDrawHooks = [];\r\n    $.jqplot.preDrawSeriesHooks = [];\r\n    $.jqplot.postDrawSeriesHooks = [];\r\n    $.jqplot.preDrawLegendHooks = [];\r\n    $.jqplot.addLegendRowHooks = [];\r\n    $.jqplot.preSeriesInitHooks = [];\r\n    $.jqplot.postSeriesInitHooks = [];\r\n    $.jqplot.preParseSeriesOptionsHooks = [];\r\n    $.jqplot.postParseSeriesOptionsHooks = [];\r\n    $.jqplot.eventListenerHooks = [];\r\n    $.jqplot.preDrawSeriesShadowHooks = [];\r\n    $.jqplot.postDrawSeriesShadowHooks = [];\r\n\r\n    // A superclass holding some common properties and methods.\r\n    $.jqplot.ElemContainer = function() {\r\n        this._elem;\r\n        this._plotWidth;\r\n        this._plotHeight;\r\n        this._plotDimensions = {height:null, width:null};\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.createElement = function(el, offsets, clss, cssopts, attrib) {\r\n        this._offsets = offsets;\r\n        var klass = clss || 'jqplot';\r\n        var elem = document.createElement(el);\r\n        this._elem = $(elem);\r\n        this._elem.addClass(klass);\r\n        this._elem.css(cssopts);\r\n        this._elem.attr(attrib);\r\n        // avoid memory leak;\r\n        elem = null;\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.getWidth = function() {\r\n        if (this._elem) {\r\n            return this._elem.outerWidth(true);\r\n        }\r\n        else {\r\n            return null;\r\n        }\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.getHeight = function() {\r\n        if (this._elem) {\r\n            return this._elem.outerHeight(true);\r\n        }\r\n        else {\r\n            return null;\r\n        }\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.getPosition = function() {\r\n        if (this._elem) {\r\n            return this._elem.position();\r\n        }\r\n        else {\r\n            return {top:null, left:null, bottom:null, right:null};\r\n        }\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.getTop = function() {\r\n        return this.getPosition().top;\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.getLeft = function() {\r\n        return this.getPosition().left;\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.getBottom = function() {\r\n        return this._elem.css('bottom');\r\n    };\r\n    \r\n    $.jqplot.ElemContainer.prototype.getRight = function() {\r\n        return this._elem.css('right');\r\n    };\r\n    \r\n\r\n    /**\r\n     * Class: Axis\r\n     * An individual axis object.  Cannot be instantiated directly, but created\r\n     * by the Plot object.  Axis properties can be set or overridden by the \r\n     * options passed in from the user.\r\n     * \r\n     */\r\n    function Axis(name) {\r\n        $.jqplot.ElemContainer.call(this);\r\n        // Group: Properties\r\n        //\r\n        // Axes options are specified within an axes object at the top level of the \r\n        // plot options like so:\r\n        // > {\r\n        // >    axes: {\r\n        // >        xaxis: {min: 5},\r\n        // >        yaxis: {min: 2, max: 8, numberTicks:4},\r\n        // >        x2axis: {pad: 1.5},\r\n        // >        y2axis: {ticks:[22, 44, 66, 88]}\r\n        // >        }\r\n        // > }\r\n        // There are 2 x axes, 'xaxis' and 'x2axis', and \r\n        // 9 yaxes, 'yaxis', 'y2axis'. 'y3axis', ...  Any or all of which may be specified.\r\n        this.name = name;\r\n        this._series = [];\r\n        // prop: show\r\n        // Wether to display the axis on the graph.\r\n        this.show = false;\r\n        // prop: tickRenderer\r\n        // A class of a rendering engine for creating the ticks labels displayed on the plot, \r\n        // See <$.jqplot.AxisTickRenderer>.\r\n        this.tickRenderer = $.jqplot.AxisTickRenderer;\r\n        // prop: tickOptions\r\n        // Options that will be passed to the tickRenderer, see <$.jqplot.AxisTickRenderer> options.\r\n        this.tickOptions = {};\r\n        // prop: labelRenderer\r\n        // A class of a rendering engine for creating an axis label.\r\n        this.labelRenderer = $.jqplot.AxisLabelRenderer;\r\n        // prop: labelOptions\r\n        // Options passed to the label renderer.\r\n        this.labelOptions = {};\r\n        // prop: label\r\n        // Label for the axis\r\n        this.label = null;\r\n        // prop: showLabel\r\n        // true to show the axis label.\r\n        this.showLabel = true;\r\n        // prop: min\r\n        // minimum value of the axis (in data units, not pixels).\r\n        this.min = null;\r\n        // prop: max\r\n        // maximum value of the axis (in data units, not pixels).\r\n        this.max = null;\r\n        // prop: autoscale\r\n        // DEPRECATED\r\n        // the default scaling algorithm produces superior results.\r\n        this.autoscale = false;\r\n        // prop: pad\r\n        // Padding to extend the range above and below the data bounds.\r\n        // The data range is multiplied by this factor to determine minimum and maximum axis bounds.\r\n        // A value of 0 will be interpreted to mean no padding, and pad will be set to 1.0.\r\n        this.pad = 1.2;\r\n        // prop: padMax\r\n        // Padding to extend the range above data bounds.\r\n        // The top of the data range is multiplied by this factor to determine maximum axis bounds.\r\n        // A value of 0 will be interpreted to mean no padding, and padMax will be set to 1.0.\r\n        this.padMax = null;\r\n        // prop: padMin\r\n        // Padding to extend the range below data bounds.\r\n        // The bottom of the data range is multiplied by this factor to determine minimum axis bounds.\r\n        // A value of 0 will be interpreted to mean no padding, and padMin will be set to 1.0.\r\n        this.padMin = null;\r\n        // prop: ticks\r\n        // 1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.\r\n        // If no label is specified, the value is formatted into an appropriate label.\r\n        this.ticks = [];\r\n        // prop: numberTicks\r\n        // Desired number of ticks.  Default is to compute automatically.\r\n        this.numberTicks;\r\n        // prop: tickInterval\r\n        // number of units between ticks.  Mutually exclusive with numberTicks.\r\n        this.tickInterval;\r\n        // prop: renderer\r\n        // A class of a rendering engine that handles tick generation, \r\n        // scaling input data to pixel grid units and drawing the axis element.\r\n        this.renderer = $.jqplot.LinearAxisRenderer;\r\n        // prop: rendererOptions\r\n        // renderer specific options.  See <$.jqplot.LinearAxisRenderer> for options.\r\n        this.rendererOptions = {};\r\n        // prop: showTicks\r\n        // Wether to show the ticks (both marks and labels) or not.\r\n        // Will not override showMark and showLabel options if specified on the ticks themselves.\r\n        this.showTicks = true;\r\n        // prop: showTickMarks\r\n        // Wether to show the tick marks (line crossing grid) or not.\r\n        // Overridden by showTicks and showMark option of tick itself.\r\n        this.showTickMarks = true;\r\n        // prop: showMinorTicks\r\n        // Wether or not to show minor ticks.  This is renderer dependent.\r\n        this.showMinorTicks = true;\r\n        // prop: drawMajorGridlines\r\n        // True to draw gridlines for major axis ticks.\r\n        this.drawMajorGridlines = true;\r\n        // prop: drawMinorGridlines\r\n        // True to draw gridlines for minor ticks.\r\n        this.drawMinorGridlines = false;\r\n        // prop: drawMajorTickMarks\r\n        // True to draw tick marks for major axis ticks.\r\n        this.drawMajorTickMarks = true;\r\n        // prop: drawMinorTickMarks\r\n        // True to draw tick marks for minor ticks.  This is renderer dependent.\r\n        this.drawMinorTickMarks = true;\r\n        // prop: useSeriesColor\r\n        // Use the color of the first series associated with this axis for the\r\n        // tick marks and line bordering this axis.\r\n        this.useSeriesColor = false;\r\n        // prop: borderWidth\r\n        // width of line stroked at the border of the axis.  Defaults\r\n        // to the width of the grid boarder.\r\n        this.borderWidth = null;\r\n        // prop: borderColor\r\n        // color of the border adjacent to the axis.  Defaults to grid border color.\r\n        this.borderColor = null;\r\n        // prop: scaleToHiddenSeries\r\n        // True to include hidden series when computing axes bounds and scaling.\r\n        this.scaleToHiddenSeries = false;\r\n        // minimum and maximum values on the axis.\r\n        this._dataBounds = {min:null, max:null};\r\n        // statistics (min, max, mean) as well as actual data intervals for each series attached to axis.\r\n        // holds collection of {intervals:[], min:, max:, mean: } objects for each series on axis.\r\n        this._intervalStats = [];\r\n        // pixel position from the top left of the min value and max value on the axis.\r\n        this._offsets = {min:null, max:null};\r\n        this._ticks=[];\r\n        this._label = null;\r\n        // prop: syncTicks\r\n        // true to try and synchronize tick spacing across multiple axes so that ticks and\r\n        // grid lines line up.  This has an impact on autoscaling algorithm, however.\r\n        // In general, autoscaling an individual axis will work better if it does not\r\n        // have to sync ticks.\r\n        this.syncTicks = null;\r\n        // prop: tickSpacing\r\n        // Approximate pixel spacing between ticks on graph.  Used during autoscaling.\r\n        // This number will be an upper bound, actual spacing will be less.\r\n        this.tickSpacing = 75;\r\n        // Properties to hold the original values for min, max, ticks, tickInterval and numberTicks\r\n        // so they can be restored if altered by plugins.\r\n        this._min = null;\r\n        this._max = null;\r\n        this._tickInterval = null;\r\n        this._numberTicks = null;\r\n        this.__ticks = null;\r\n        // hold original user options.\r\n        this._options = {};\r\n    }\r\n    \r\n    Axis.prototype = new $.jqplot.ElemContainer();\r\n    Axis.prototype.constructor = Axis;\r\n    \r\n    Axis.prototype.init = function() {\r\n        if ($.isFunction(this.renderer)) {\r\n            this.renderer = new this.renderer();  \r\n        }\r\n        // set the axis name\r\n        this.tickOptions.axis = this.name;\r\n        // if showMark or showLabel tick options not specified, use value of axis option.\r\n        // showTicks overrides showTickMarks.\r\n        if (this.tickOptions.showMark == null) {\r\n            this.tickOptions.showMark = this.showTicks;\r\n        }\r\n        if (this.tickOptions.showMark == null) {\r\n            this.tickOptions.showMark = this.showTickMarks;\r\n        }\r\n        if (this.tickOptions.showLabel == null) {\r\n            this.tickOptions.showLabel = this.showTicks;\r\n        }\r\n        \r\n        if (this.label == null || this.label == '') {\r\n            this.showLabel = false;\r\n        }\r\n        else {\r\n            this.labelOptions.label = this.label;\r\n        }\r\n        if (this.showLabel == false) {\r\n            this.labelOptions.show = false;\r\n        }\r\n        // set the default padMax, padMin if not specified\r\n        // special check, if no padding desired, padding\r\n        // should be set to 1.0\r\n        if (this.pad == 0) {\r\n            this.pad = 1.0;\r\n        }\r\n        if (this.padMax == 0) {\r\n            this.padMax = 1.0;\r\n        }\r\n        if (this.padMin == 0) {\r\n            this.padMin = 1.0;\r\n        }\r\n        if (this.padMax == null) {\r\n            this.padMax = (this.pad-1)/2 + 1;\r\n        }\r\n        if (this.padMin == null) {\r\n            this.padMin = (this.pad-1)/2 + 1;\r\n        }\r\n        // now that padMin and padMax are correctly set, reset pad in case user has supplied \r\n        // padMin and/or padMax\r\n        this.pad = this.padMax + this.padMin - 1;\r\n        if (this.min != null || this.max != null) {\r\n            this.autoscale = false;\r\n        }\r\n        // if not set, sync ticks for y axes but not x by default.\r\n        if (this.syncTicks == null && this.name.indexOf('y') > -1) {\r\n            this.syncTicks = true;\r\n        }\r\n        else if (this.syncTicks == null){\r\n            this.syncTicks = false;\r\n        }\r\n        this.renderer.init.call(this, this.rendererOptions);\r\n        \r\n    };\r\n    \r\n    Axis.prototype.draw = function(ctx, plot) {\r\n        // Memory Leaks patch\r\n        if (this.__ticks) {\r\n          this.__ticks = null;\r\n        }\r\n\r\n        return this.renderer.draw.call(this, ctx, plot);\r\n        \r\n    };\r\n    \r\n    Axis.prototype.set = function() {\r\n        this.renderer.set.call(this);\r\n    };\r\n    \r\n    Axis.prototype.pack = function(pos, offsets) {\r\n        if (this.show) {\r\n            this.renderer.pack.call(this, pos, offsets);\r\n        }\r\n        // these properties should all be available now.\r\n        if (this._min == null) {\r\n            this._min = this.min;\r\n            this._max = this.max;\r\n            this._tickInterval = this.tickInterval;\r\n            this._numberTicks = this.numberTicks;\r\n            this.__ticks = this._ticks;\r\n        }\r\n    };\r\n    \r\n    // reset the axis back to original values if it has been scaled, zoomed, etc.\r\n    Axis.prototype.reset = function() {\r\n        this.renderer.reset.call(this);\r\n    };\r\n    \r\n    Axis.prototype.resetScale = function(opts) {\r\n        $.extend(true, this, {min: null, max: null, numberTicks: null, tickInterval: null, _ticks: [], ticks: []}, opts);\r\n        this.resetDataBounds();\r\n    };\r\n    \r\n    Axis.prototype.resetDataBounds = function() {\r\n        // Go through all the series attached to this axis and find\r\n        // the min/max bounds for this axis.\r\n        var db = this._dataBounds;\r\n        db.min = null;\r\n        db.max = null;\r\n        var l, s, d;\r\n        // check for when to force min 0 on bar series plots.\r\n        var doforce = (this.show) ? true : false;\r\n        for (var i=0; i<this._series.length; i++) {\r\n            s = this._series[i];\r\n            if (s.show || this.scaleToHiddenSeries) {\r\n                d = s._plotData;\r\n                if (s._type === 'line' && s.renderer.bands.show && this.name.charAt(0) !== 'x') {\r\n                    d = [[0, s.renderer.bands._min], [1, s.renderer.bands._max]];\r\n                }\r\n\r\n                var minyidx = 1, maxyidx = 1;\r\n\r\n                if (s._type != null && s._type == 'ohlc') {\r\n                    minyidx = 3;\r\n                    maxyidx = 2;\r\n                }\r\n                \r\n                for (var j=0, l=d.length; j<l; j++) { \r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) {\r\n                            db.min = d[j][0];\r\n                        }\r\n                        if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) {\r\n                            db.max = d[j][0];\r\n                        }\r\n                    }              \r\n                    else {\r\n                        if ((d[j][minyidx] != null && d[j][minyidx] < db.min) || db.min == null) {\r\n                            db.min = d[j][minyidx];\r\n                        }\r\n                        if ((d[j][maxyidx] != null && d[j][maxyidx] > db.max) || db.max == null) {\r\n                            db.max = d[j][maxyidx];\r\n                        }\r\n                    }              \r\n                }\r\n\r\n                // Hack to not pad out bottom of bar plots unless user has specified a padding.\r\n                // every series will have a chance to set doforce to false.  once it is set to \r\n                // false, it cannot be reset to true.\r\n                // If any series attached to axis is not a bar, wont force 0.\r\n                if (doforce && s.renderer.constructor !== $.jqplot.BarRenderer) {\r\n                    doforce = false;\r\n                }\r\n\r\n                else if (doforce && this._options.hasOwnProperty('forceTickAt0') && this._options.forceTickAt0 == false) {\r\n                    doforce = false;\r\n                }\r\n\r\n                else if (doforce && s.renderer.constructor === $.jqplot.BarRenderer) {\r\n                    if (s.barDirection == 'vertical' && this.name != 'xaxis' && this.name != 'x2axis') { \r\n                        if (this._options.pad != null || this._options.padMin != null) {\r\n                            doforce = false;\r\n                        }\r\n                    }\r\n\r\n                    else if (s.barDirection == 'horizontal' && (this.name == 'xaxis' || this.name == 'x2axis')) {\r\n                        if (this._options.pad != null || this._options.padMin != null) {\r\n                            doforce = false;\r\n                        }\r\n                    }\r\n\r\n                }\r\n            }\r\n        }\r\n\r\n        if (doforce && this.renderer.constructor === $.jqplot.LinearAxisRenderer && db.min >= 0) {\r\n            this.padMin = 1.0;\r\n            this.forceTickAt0 = true;\r\n        }\r\n    };\r\n\r\n    /**\r\n     * Class: Legend\r\n     * Legend object.  Cannot be instantiated directly, but created\r\n     * by the Plot object.  Legend properties can be set or overridden by the \r\n     * options passed in from the user.\r\n     */\r\n    function Legend(options) {\r\n        $.jqplot.ElemContainer.call(this);\r\n        // Group: Properties\r\n        \r\n        // prop: show\r\n        // Wether to display the legend on the graph.\r\n        this.show = false;\r\n        // prop: location\r\n        // Placement of the legend.  one of the compass directions: nw, n, ne, e, se, s, sw, w\r\n        this.location = 'ne';\r\n        // prop: labels\r\n        // Array of labels to use.  By default the renderer will look for labels on the series.\r\n        // Labels specified in this array will override labels specified on the series.\r\n        this.labels = [];\r\n        // prop: showLabels\r\n        // true to show the label text on the  legend.\r\n        this.showLabels = true;\r\n        // prop: showSwatch\r\n        // true to show the color swatches on the legend.\r\n        this.showSwatches = true;\r\n        // prop: placement\r\n        // \"insideGrid\" places legend inside the grid area of the plot.\r\n        // \"outsideGrid\" places the legend outside the grid but inside the plot container, \r\n        // shrinking the grid to accomodate the legend.\r\n        // \"inside\" synonym for \"insideGrid\", \r\n        // \"outside\" places the legend ouside the grid area, but does not shrink the grid which\r\n        // can cause the legend to overflow the plot container.\r\n        this.placement = \"insideGrid\";\r\n        // prop: xoffset\r\n        // DEPRECATED.  Set the margins on the legend using the marginTop, marginLeft, etc. \r\n        // properties or via CSS margin styling of the .jqplot-table-legend class.\r\n        this.xoffset = 0;\r\n        // prop: yoffset\r\n        // DEPRECATED.  Set the margins on the legend using the marginTop, marginLeft, etc. \r\n        // properties or via CSS margin styling of the .jqplot-table-legend class.\r\n        this.yoffset = 0;\r\n        // prop: border\r\n        // css spec for the border around the legend box.\r\n        this.border;\r\n        // prop: background\r\n        // css spec for the background of the legend box.\r\n        this.background;\r\n        // prop: textColor\r\n        // css color spec for the legend text.\r\n        this.textColor;\r\n        // prop: fontFamily\r\n        // css font-family spec for the legend text.\r\n        this.fontFamily; \r\n        // prop: fontSize\r\n        // css font-size spec for the legend text.\r\n        this.fontSize ;\r\n        // prop: rowSpacing\r\n        // css padding-top spec for the rows in the legend.\r\n        this.rowSpacing = '0.5em';\r\n        // renderer\r\n        // A class that will create a DOM object for the legend,\r\n        // see <$.jqplot.TableLegendRenderer>.\r\n        this.renderer = $.jqplot.TableLegendRenderer;\r\n        // prop: rendererOptions\r\n        // renderer specific options passed to the renderer.\r\n        this.rendererOptions = {};\r\n        // prop: predraw\r\n        // Wether to draw the legend before the series or not.\r\n        // Used with series specific legend renderers for pie, donut, mekko charts, etc.\r\n        this.preDraw = false;\r\n        // prop: marginTop\r\n        // CSS margin for the legend DOM element. This will set an element \r\n        // CSS style for the margin which will override any style sheet setting.\r\n        // The default will be taken from the stylesheet.\r\n        this.marginTop = null;\r\n        // prop: marginRight\r\n        // CSS margin for the legend DOM element. This will set an element \r\n        // CSS style for the margin which will override any style sheet setting.\r\n        // The default will be taken from the stylesheet.\r\n        this.marginRight = null;\r\n        // prop: marginBottom\r\n        // CSS margin for the legend DOM element. This will set an element \r\n        // CSS style for the margin which will override any style sheet setting.\r\n        // The default will be taken from the stylesheet.\r\n        this.marginBottom = null;\r\n        // prop: marginLeft\r\n        // CSS margin for the legend DOM element. This will set an element \r\n        // CSS style for the margin which will override any style sheet setting.\r\n        // The default will be taken from the stylesheet.\r\n        this.marginLeft = null;\r\n        // prop: escapeHtml\r\n        // True to escape special characters with their html entity equivalents\r\n        // in legend text.  \"<\" becomes &lt; and so on, so html tags are not rendered.\r\n        this.escapeHtml = false;\r\n        this._series = [];\r\n        \r\n        $.extend(true, this, options);\r\n    }\r\n    \r\n    Legend.prototype = new $.jqplot.ElemContainer();\r\n    Legend.prototype.constructor = Legend;\r\n    \r\n    Legend.prototype.setOptions = function(options) {\r\n        $.extend(true, this, options);\r\n        \r\n        // Try to emulate deprecated behaviour\r\n        // if user has specified xoffset or yoffset, copy these to\r\n        // the margin properties.\r\n        \r\n        if (this.placement ==  'inside') {\r\n            this.placement = 'insideGrid';\r\n        }\r\n        \r\n        if (this.xoffset >0) {\r\n            if (this.placement == 'insideGrid') {\r\n                switch (this.location) {\r\n                    case 'nw':\r\n                    case 'w':\r\n                    case 'sw':\r\n                        if (this.marginLeft == null) {\r\n                            this.marginLeft = this.xoffset + 'px';\r\n                        }\r\n                        this.marginRight = '0px';\r\n                        break;\r\n                    case 'ne':\r\n                    case 'e':\r\n                    case 'se':\r\n                    default:\r\n                        if (this.marginRight == null) {\r\n                            this.marginRight = this.xoffset + 'px';\r\n                        }\r\n                        this.marginLeft = '0px';\r\n                        break;\r\n                }\r\n            }\r\n            else if (this.placement == 'outside') {\r\n                switch (this.location) {\r\n                    case 'nw':\r\n                    case 'w':\r\n                    case 'sw':\r\n                        if (this.marginRight == null) {\r\n                            this.marginRight = this.xoffset + 'px';\r\n                        }\r\n                        this.marginLeft = '0px';\r\n                        break;\r\n                    case 'ne':\r\n                    case 'e':\r\n                    case 'se':\r\n                    default:\r\n                        if (this.marginLeft == null) {\r\n                            this.marginLeft = this.xoffset + 'px';\r\n                        }\r\n                        this.marginRight = '0px';\r\n                        break;\r\n                }\r\n            }\r\n            this.xoffset = 0;\r\n        }\r\n        \r\n        if (this.yoffset >0) {\r\n            if (this.placement == 'outside') {\r\n                switch (this.location) {\r\n                    case 'sw':\r\n                    case 's':\r\n                    case 'se':\r\n                        if (this.marginTop == null) {\r\n                            this.marginTop = this.yoffset + 'px';\r\n                        }\r\n                        this.marginBottom = '0px';\r\n                        break;\r\n                    case 'ne':\r\n                    case 'n':\r\n                    case 'nw':\r\n                    default:\r\n                        if (this.marginBottom == null) {\r\n                            this.marginBottom = this.yoffset + 'px';\r\n                        }\r\n                        this.marginTop = '0px';\r\n                        break;\r\n                }\r\n            }\r\n            else if (this.placement == 'insideGrid') {\r\n                switch (this.location) {\r\n                    case 'sw':\r\n                    case 's':\r\n                    case 'se':\r\n                        if (this.marginBottom == null) {\r\n                            this.marginBottom = this.yoffset + 'px';\r\n                        }\r\n                        this.marginTop = '0px';\r\n                        break;\r\n                    case 'ne':\r\n                    case 'n':\r\n                    case 'nw':\r\n                    default:\r\n                        if (this.marginTop == null) {\r\n                            this.marginTop = this.yoffset + 'px';\r\n                        }\r\n                        this.marginBottom = '0px';\r\n                        break;\r\n                }\r\n            }\r\n            this.yoffset = 0;\r\n        }\r\n        \r\n        // TO-DO:\r\n        // Handle case where offsets are < 0.\r\n        //\r\n    };\r\n    \r\n    Legend.prototype.init = function() {\r\n        if ($.isFunction(this.renderer)) {\r\n            this.renderer = new this.renderer();  \r\n        }\r\n        this.renderer.init.call(this, this.rendererOptions);\r\n    };\r\n    \r\n    Legend.prototype.draw = function(offsets, plot) {\r\n        for (var i=0; i<$.jqplot.preDrawLegendHooks.length; i++){\r\n            $.jqplot.preDrawLegendHooks[i].call(this, offsets);\r\n        }\r\n        return this.renderer.draw.call(this, offsets, plot);\r\n    };\r\n    \r\n    Legend.prototype.pack = function(offsets) {\r\n        this.renderer.pack.call(this, offsets);\r\n    };\r\n\r\n    /**\r\n     * Class: Title\r\n     * Plot Title object.  Cannot be instantiated directly, but created\r\n     * by the Plot object.  Title properties can be set or overridden by the \r\n     * options passed in from the user.\r\n     * \r\n     * Parameters:\r\n     * text - text of the title.\r\n     */\r\n    function Title(text) {\r\n        $.jqplot.ElemContainer.call(this);\r\n        // Group: Properties\r\n        \r\n        // prop: text\r\n        // text of the title;\r\n        this.text = text;\r\n        // prop: show\r\n        // whether or not to show the title\r\n        this.show = true;\r\n        // prop: fontFamily\r\n        // css font-family spec for the text.\r\n        this.fontFamily;\r\n        // prop: fontSize\r\n        // css font-size spec for the text.\r\n        this.fontSize ;\r\n        // prop: textAlign\r\n        // css text-align spec for the text.\r\n        this.textAlign;\r\n        // prop: textColor\r\n        // css color spec for the text.\r\n        this.textColor;\r\n        // prop: renderer\r\n        // A class for creating a DOM element for the title,\r\n        // see <$.jqplot.DivTitleRenderer>.\r\n        this.renderer = $.jqplot.DivTitleRenderer;\r\n        // prop: rendererOptions\r\n        // renderer specific options passed to the renderer.\r\n        this.rendererOptions = {};   \r\n        // prop: escapeHtml\r\n        // True to escape special characters with their html entity equivalents\r\n        // in title text.  \"<\" becomes &lt; and so on, so html tags are not rendered.\r\n        this.escapeHtml = false;\r\n    }\r\n    \r\n    Title.prototype = new $.jqplot.ElemContainer();\r\n    Title.prototype.constructor = Title;\r\n    \r\n    Title.prototype.init = function() {\r\n        if ($.isFunction(this.renderer)) {\r\n            this.renderer = new this.renderer();  \r\n        }\r\n        this.renderer.init.call(this, this.rendererOptions);\r\n    };\r\n    \r\n    Title.prototype.draw = function(width) {\r\n        return this.renderer.draw.call(this, width);\r\n    };\r\n    \r\n    Title.prototype.pack = function() {\r\n        this.renderer.pack.call(this);\r\n    };\r\n\r\n\r\n    /**\r\n     * Class: Series\r\n     * An individual data series object.  Cannot be instantiated directly, but created\r\n     * by the Plot object.  Series properties can be set or overridden by the \r\n     * options passed in from the user.\r\n     */\r\n    function Series(options) {\r\n        options = options || {};\r\n        $.jqplot.ElemContainer.call(this);\r\n        // Group: Properties\r\n        // Properties will be assigned from a series array at the top level of the\r\n        // options.  If you had two series and wanted to change the color and line\r\n        // width of the first and set the second to use the secondary y axis with\r\n        // no shadow and supply custom labels for each:\r\n        // > {\r\n        // >    series:[\r\n        // >        {color: '#ff4466', lineWidth: 5, label:'good line'},\r\n        // >        {yaxis: 'y2axis', shadow: false, label:'bad line'}\r\n        // >    ]\r\n        // > }\r\n\r\n        // prop: show\r\n        // whether or not to draw the series.\r\n        this.show = true;\r\n        // prop: xaxis\r\n        // which x axis to use with this series, either 'xaxis' or 'x2axis'.\r\n        this.xaxis = 'xaxis';\r\n        this._xaxis;\r\n        // prop: yaxis\r\n        // which y axis to use with this series, either 'yaxis' or 'y2axis'.\r\n        this.yaxis = 'yaxis';\r\n        this._yaxis;\r\n        this.gridBorderWidth = 2.0;\r\n        // prop: renderer\r\n        // A class of a renderer which will draw the series, \r\n        // see <$.jqplot.LineRenderer>.\r\n        this.renderer = $.jqplot.LineRenderer;\r\n        // prop: rendererOptions\r\n        // Options to pass on to the renderer.\r\n        this.rendererOptions = {};\r\n        this.data = [];\r\n        this.gridData = [];\r\n        // prop: label\r\n        // Line label to use in the legend.\r\n        this.label = '';\r\n        // prop: showLabel\r\n        // true to show label for this series in the legend.\r\n        this.showLabel = true;\r\n        // prop: color\r\n        // css color spec for the series\r\n        this.color;\r\n        // prop: negativeColor\r\n        // css color spec used for filled (area) plots that are filled to zero and\r\n        // the \"useNegativeColors\" option is true.\r\n        this.negativeColor;\r\n        // prop: lineWidth\r\n        // width of the line in pixels.  May have different meanings depending on renderer.\r\n        this.lineWidth = 2.5;\r\n        // prop: lineJoin\r\n        // Canvas lineJoin style between segments of series.\r\n        this.lineJoin = 'round';\r\n        // prop: lineCap\r\n        // Canvas lineCap style at ends of line.\r\n        this.lineCap = 'round';\r\n        // prop: linePattern\r\n        // line pattern 'dashed', 'dotted', 'solid', some combination\r\n        // of '-' and '.' characters such as '.-.' or a numerical array like \r\n        // [draw, skip, draw, skip, ...] such as [1, 10] to draw a dotted line, \r\n        // [1, 10, 20, 10] to draw a dot-dash line, and so on.\r\n        this.linePattern = 'solid';\r\n        this.shadow = true;\r\n        // prop: shadowAngle\r\n        // Shadow angle in degrees\r\n        this.shadowAngle = 45;\r\n        // prop: shadowOffset\r\n        // Shadow offset from line in pixels\r\n        this.shadowOffset = 1.25;\r\n        // prop: shadowDepth\r\n        // Number of times shadow is stroked, each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 3;\r\n        // prop: shadowAlpha\r\n        // Alpha channel transparency of shadow.  0 = transparent.\r\n        this.shadowAlpha = '0.1';\r\n        // prop: breakOnNull\r\n        // Wether line segments should be be broken at null value.\r\n        // False will join point on either side of line.\r\n        this.breakOnNull = false;\r\n        // prop: markerRenderer\r\n        // A class of a renderer which will draw marker (e.g. circle, square, ...) at the data points,\r\n        // see <$.jqplot.MarkerRenderer>.\r\n        this.markerRenderer = $.jqplot.MarkerRenderer;\r\n        // prop: markerOptions\r\n        // renderer specific options to pass to the markerRenderer,\r\n        // see <$.jqplot.MarkerRenderer>.\r\n        this.markerOptions = {};\r\n        // prop: showLine\r\n        // whether to actually draw the line or not.  Series will still be renderered, even if no line is drawn.\r\n        this.showLine = true;\r\n        // prop: showMarker\r\n        // whether or not to show the markers at the data points.\r\n        this.showMarker = true;\r\n        // prop: index\r\n        // 0 based index of this series in the plot series array.\r\n        this.index;\r\n        // prop: fill\r\n        // true or false, whether to fill under lines or in bars.\r\n        // May not be implemented in all renderers.\r\n        this.fill = false;\r\n        // prop: fillColor\r\n        // CSS color spec to use for fill under line.  Defaults to line color.\r\n        this.fillColor;\r\n        // prop: fillAlpha\r\n        // Alpha transparency to apply to the fill under the line.\r\n        // Use this to adjust alpha separate from fill color.\r\n        this.fillAlpha;\r\n        // prop: fillAndStroke\r\n        // If true will stroke the line (with color this.color) as well as fill under it.\r\n        // Applies only when fill is true.\r\n        this.fillAndStroke = false;\r\n        // prop: disableStack\r\n        // true to not stack this series with other series in the plot.\r\n        // To render properly, non-stacked series must come after any stacked series\r\n        // in the plot's data series array.  So, the plot's data series array would look like:\r\n        // > [stackedSeries1, stackedSeries2, ..., nonStackedSeries1, nonStackedSeries2, ...]\r\n        // disableStack will put a gap in the stacking order of series, and subsequent\r\n        // stacked series will not fill down through the non-stacked series and will\r\n        // most likely not stack properly on top of the non-stacked series.\r\n        this.disableStack = false;\r\n        // _stack is set by the Plot if the plot is a stacked chart.\r\n        // will stack lines or bars on top of one another to build a \"mountain\" style chart.\r\n        // May not be implemented in all renderers.\r\n        this._stack = false;\r\n        // prop: neighborThreshold\r\n        // how close or far (in pixels) the cursor must be from a point marker to detect the point.\r\n        this.neighborThreshold = 4;\r\n        // prop: fillToZero\r\n        // true will force bar and filled series to fill toward zero on the fill Axis.\r\n        this.fillToZero = false;\r\n        // prop: fillToValue\r\n        // fill a filled series to this value on the fill axis.\r\n        // Works in conjunction with fillToZero, so that must be true.\r\n        this.fillToValue = 0;\r\n        // prop: fillAxis\r\n        // Either 'x' or 'y'.  Which axis to fill the line toward if fillToZero is true.\r\n        // 'y' means fill up/down to 0 on the y axis for this series.\r\n        this.fillAxis = 'y';\r\n        // prop: useNegativeColors\r\n        // true to color negative values differently in filled and bar charts.\r\n        this.useNegativeColors = true;\r\n        this._stackData = [];\r\n        // _plotData accounts for stacking.  If plots not stacked, _plotData and data are same.  If\r\n        // stacked, _plotData is accumulation of stacking data.\r\n        this._plotData = [];\r\n        // _plotValues hold the individual x and y values that will be plotted for this series.\r\n        this._plotValues = {x:[], y:[]};\r\n        // statistics about the intervals between data points.  Used for auto scaling.\r\n        this._intervals = {x:{}, y:{}};\r\n        // data from the previous series, for stacked charts.\r\n        this._prevPlotData = [];\r\n        this._prevGridData = [];\r\n        this._stackAxis = 'y';\r\n        this._primaryAxis = '_xaxis';\r\n        // give each series a canvas to draw on.  This should allow for redrawing speedups.\r\n        this.canvas = new $.jqplot.GenericCanvas();\r\n        this.shadowCanvas = new $.jqplot.GenericCanvas();\r\n        this.plugins = {};\r\n        // sum of y values in this series.\r\n        this._sumy = 0;\r\n        this._sumx = 0;\r\n        this._type = '';\r\n        this.step = false;\r\n    }\r\n    \r\n    Series.prototype = new $.jqplot.ElemContainer();\r\n    Series.prototype.constructor = Series;\r\n    \r\n    Series.prototype.init = function(index, gridbw, plot) {\r\n        // weed out any null values in the data.\r\n        this.index = index;\r\n        this.gridBorderWidth = gridbw;\r\n        var d = this.data;\r\n        var temp = [], i, l;\r\n        for (i=0, l=d.length; i<l; i++) {\r\n            if (! this.breakOnNull) {\r\n                if (d[i] == null || d[i][0] == null || d[i][1] == null) {\r\n                    continue;\r\n                }\r\n                else {\r\n                    temp.push(d[i]);\r\n                }\r\n            }\r\n            else {\r\n                // TODO: figure out what to do with null values\r\n                // probably involve keeping nulls in data array\r\n                // and then updating renderers to break line\r\n                // when it hits null value.\r\n                // For now, just keep value.\r\n                temp.push(d[i]);\r\n            }\r\n        }\r\n        this.data = temp;\r\n\r\n        // parse the renderer options and apply default colors if not provided\r\n        // Set color even if not shown, so series don't change colors when other\r\n        // series on plot shown/hidden.\r\n        if (!this.color) {\r\n            this.color = plot.colorGenerator.get(this.index);\r\n        }\r\n        if (!this.negativeColor) {\r\n            this.negativeColor = plot.negativeColorGenerator.get(this.index);\r\n        }\r\n\r\n\r\n        if (!this.fillColor) {\r\n            this.fillColor = this.color;\r\n        }\r\n        if (this.fillAlpha) {\r\n            var comp = $.jqplot.normalize2rgb(this.fillColor);\r\n            var comp = $.jqplot.getColorComponents(comp);\r\n            this.fillColor = 'rgba('+comp[0]+','+comp[1]+','+comp[2]+','+this.fillAlpha+')';\r\n        }\r\n        if ($.isFunction(this.renderer)) {\r\n            this.renderer = new this.renderer();  \r\n        }\r\n        this.renderer.init.call(this, this.rendererOptions, plot);\r\n        this.markerRenderer = new this.markerRenderer();\r\n        if (!this.markerOptions.color) {\r\n            this.markerOptions.color = this.color;\r\n        }\r\n        if (this.markerOptions.show == null) {\r\n            this.markerOptions.show = this.showMarker;\r\n        }\r\n        this.showMarker = this.markerOptions.show;\r\n        // the markerRenderer is called within its own scope, don't want to overwrite series options!!\r\n        this.markerRenderer.init(this.markerOptions);\r\n    };\r\n    \r\n    // data - optional data point array to draw using this series renderer\r\n    // gridData - optional grid data point array to draw using this series renderer\r\n    // stackData - array of cumulative data for stacked plots.\r\n    Series.prototype.draw = function(sctx, opts, plot) {\r\n        var options = (opts == undefined) ? {} : opts;\r\n        sctx = (sctx == undefined) ? this.canvas._ctx : sctx;\r\n        \r\n        var j, data, gridData;\r\n        \r\n        // hooks get called even if series not shown\r\n        // we don't clear canvas here, it would wipe out all other series as well.\r\n        for (j=0; j<$.jqplot.preDrawSeriesHooks.length; j++) {\r\n            $.jqplot.preDrawSeriesHooks[j].call(this, sctx, options);\r\n        }\r\n        if (this.show) {\r\n            this.renderer.setGridData.call(this, plot);\r\n            if (!options.preventJqPlotSeriesDrawTrigger) {\r\n                $(sctx.canvas).trigger('jqplotSeriesDraw', [this.data, this.gridData]);\r\n            }\r\n            data = [];\r\n            if (options.data) {\r\n                data = options.data;\r\n            }\r\n            else if (!this._stack) {\r\n                data = this.data;\r\n            }\r\n            else {\r\n                data = this._plotData;\r\n            }\r\n            gridData = options.gridData || this.renderer.makeGridData.call(this, data, plot);\r\n\r\n            if (this._type === 'line' && this.renderer.smooth && this.renderer._smoothedData.length) {\r\n                gridData = this.renderer._smoothedData;\r\n            }\r\n\r\n            this.renderer.draw.call(this, sctx, gridData, options, plot);\r\n        }\r\n        \r\n        for (j=0; j<$.jqplot.postDrawSeriesHooks.length; j++) {\r\n            $.jqplot.postDrawSeriesHooks[j].call(this, sctx, options, plot);\r\n        }\r\n        \r\n        sctx = opts = plot = j = data = gridData = null;\r\n    };\r\n    \r\n    Series.prototype.drawShadow = function(sctx, opts, plot) {\r\n        var options = (opts == undefined) ? {} : opts;\r\n        sctx = (sctx == undefined) ? this.shadowCanvas._ctx : sctx;\r\n        \r\n        var j, data, gridData;\r\n        \r\n        // hooks get called even if series not shown\r\n        // we don't clear canvas here, it would wipe out all other series as well.\r\n        for (j=0; j<$.jqplot.preDrawSeriesShadowHooks.length; j++) {\r\n            $.jqplot.preDrawSeriesShadowHooks[j].call(this, sctx, options);\r\n        }\r\n        if (this.shadow) {\r\n            this.renderer.setGridData.call(this, plot);\r\n\r\n            data = [];\r\n            if (options.data) {\r\n                data = options.data;\r\n            }\r\n            else if (!this._stack) {\r\n                data = this.data;\r\n            }\r\n            else {\r\n                data = this._plotData;\r\n            }\r\n            gridData = options.gridData || this.renderer.makeGridData.call(this, data, plot);\r\n        \r\n            this.renderer.drawShadow.call(this, sctx, gridData, options, plot);\r\n        }\r\n        \r\n        for (j=0; j<$.jqplot.postDrawSeriesShadowHooks.length; j++) {\r\n            $.jqplot.postDrawSeriesShadowHooks[j].call(this, sctx, options);\r\n        }\r\n        \r\n        sctx = opts = plot = j = data = gridData = null;\r\n        \r\n    };\r\n    \r\n    // toggles series display on plot, e.g. show/hide series\r\n    Series.prototype.toggleDisplay = function(ev, callback) {\r\n        var s, speed;\r\n        if (ev.data.series) {\r\n            s = ev.data.series;\r\n        }\r\n        else {\r\n            s = this;\r\n        }\r\n\r\n        if (ev.data.speed) {\r\n            speed = ev.data.speed;\r\n        }\r\n        if (speed) {\r\n            // this can be tricky because series may not have a canvas element if replotting.\r\n            if (s.canvas._elem.is(':hidden') || !s.show) {\r\n                s.show = true;\r\n\r\n                s.canvas._elem.removeClass('jqplot-series-hidden');\r\n                if (s.shadowCanvas._elem) {\r\n                    s.shadowCanvas._elem.fadeIn(speed);\r\n                }\r\n                s.canvas._elem.fadeIn(speed, callback);\r\n                s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).fadeIn(speed);\r\n            }\r\n            else {\r\n                s.show = false;\r\n\r\n                s.canvas._elem.addClass('jqplot-series-hidden');\r\n                if (s.shadowCanvas._elem) {\r\n                    s.shadowCanvas._elem.fadeOut(speed);\r\n                }\r\n                s.canvas._elem.fadeOut(speed, callback);\r\n                s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).fadeOut(speed);\r\n            }\r\n        }\r\n        else {\r\n            // this can be tricky because series may not have a canvas element if replotting.\r\n            if (s.canvas._elem.is(':hidden') || !s.show) {\r\n                s.show = true;\r\n\r\n                s.canvas._elem.removeClass('jqplot-series-hidden');\r\n                if (s.shadowCanvas._elem) {\r\n                    s.shadowCanvas._elem.show();\r\n                }\r\n                s.canvas._elem.show(0, callback);\r\n                s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).show();\r\n            }\r\n            else {\r\n                s.show = false;\r\n\r\n                s.canvas._elem.addClass('jqplot-series-hidden');\r\n                if (s.shadowCanvas._elem) {\r\n                    s.shadowCanvas._elem.hide();\r\n                }\r\n                s.canvas._elem.hide(0, callback);\r\n                s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).hide();\r\n            }\r\n        }\r\n    };\r\n    \r\n\r\n\r\n    /**\r\n     * Class: Grid\r\n     * \r\n     * Object representing the grid on which the plot is drawn.  The grid in this\r\n     * context is the area bounded by the axes, the area which will contain the series.\r\n     * Note, the series are drawn on their own canvas.\r\n     * The Grid object cannot be instantiated directly, but is created by the Plot object.  \r\n     * Grid properties can be set or overridden by the options passed in from the user.\r\n     */\r\n    function Grid() {\r\n        $.jqplot.ElemContainer.call(this);\r\n        // Group: Properties\r\n        \r\n        // prop: drawGridlines\r\n        // whether to draw the gridlines on the plot.\r\n        this.drawGridlines = true;\r\n        // prop: gridLineColor\r\n        // color of the grid lines.\r\n        this.gridLineColor = '#cccccc';\r\n        // prop: gridLineWidth\r\n        // width of the grid lines.\r\n        this.gridLineWidth = 1.0;\r\n        // prop: background\r\n        // css spec for the background color.\r\n        this.background = '#fffdf6';\r\n        // prop: borderColor\r\n        // css spec for the color of the grid border.\r\n        this.borderColor = '#999999';\r\n        // prop: borderWidth\r\n        // width of the border in pixels.\r\n        this.borderWidth = 2.0;\r\n        // prop: drawBorder\r\n        // True to draw border around grid.\r\n        this.drawBorder = true;\r\n        // prop: shadow\r\n        // whether to show a shadow behind the grid.\r\n        this.shadow = true;\r\n        // prop: shadowAngle\r\n        // shadow angle in degrees\r\n        this.shadowAngle = 45;\r\n        // prop: shadowOffset\r\n        // Offset of each shadow stroke from the border in pixels\r\n        this.shadowOffset = 1.5;\r\n        // prop: shadowWidth\r\n        // width of the stoke for the shadow\r\n        this.shadowWidth = 3;\r\n        // prop: shadowDepth\r\n        // Number of times shadow is stroked, each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 3;\r\n        // prop: shadowColor\r\n        // an optional css color spec for the shadow in 'rgba(n, n, n, n)' form\r\n        this.shadowColor = null;\r\n        // prop: shadowAlpha\r\n        // Alpha channel transparency of shadow.  0 = transparent.\r\n        this.shadowAlpha = '0.07';\r\n        this._left;\r\n        this._top;\r\n        this._right;\r\n        this._bottom;\r\n        this._width;\r\n        this._height;\r\n        this._axes = [];\r\n        // prop: renderer\r\n        // Instance of a renderer which will actually render the grid,\r\n        // see <$.jqplot.CanvasGridRenderer>.\r\n        this.renderer = $.jqplot.CanvasGridRenderer;\r\n        // prop: rendererOptions\r\n        // Options to pass on to the renderer,\r\n        // see <$.jqplot.CanvasGridRenderer>.\r\n        this.rendererOptions = {};\r\n        this._offsets = {top:null, bottom:null, left:null, right:null};\r\n    }\r\n    \r\n    Grid.prototype = new $.jqplot.ElemContainer();\r\n    Grid.prototype.constructor = Grid;\r\n    \r\n    Grid.prototype.init = function() {\r\n        if ($.isFunction(this.renderer)) {\r\n            this.renderer = new this.renderer();  \r\n        }\r\n        this.renderer.init.call(this, this.rendererOptions);\r\n    };\r\n    \r\n    Grid.prototype.createElement = function(offsets,plot) {\r\n        this._offsets = offsets;\r\n        return this.renderer.createElement.call(this, plot);\r\n    };\r\n    \r\n    Grid.prototype.draw = function() {\r\n        this.renderer.draw.call(this);\r\n    };\r\n    \r\n    $.jqplot.GenericCanvas = function() {\r\n        $.jqplot.ElemContainer.call(this);\r\n        this._ctx;  \r\n    };\r\n    \r\n    $.jqplot.GenericCanvas.prototype = new $.jqplot.ElemContainer();\r\n    $.jqplot.GenericCanvas.prototype.constructor = $.jqplot.GenericCanvas;\r\n    \r\n    $.jqplot.GenericCanvas.prototype.createElement = function(offsets, clss, plotDimensions, plot) {\r\n        this._offsets = offsets;\r\n        var klass = 'jqplot';\r\n        if (clss != undefined) {\r\n            klass = clss;\r\n        }\r\n        var elem;\r\n\r\n        elem = plot.canvasManager.getCanvas();\r\n        \r\n        // if new plotDimensions supplied, use them.\r\n        if (plotDimensions != null) {\r\n            this._plotDimensions = plotDimensions;\r\n        }\r\n        \r\n        elem.width = this._plotDimensions.width - this._offsets.left - this._offsets.right;\r\n        elem.height = this._plotDimensions.height - this._offsets.top - this._offsets.bottom;\r\n        this._elem = $(elem);\r\n        this._elem.css({ position: 'absolute', left: this._offsets.left, top: this._offsets.top });\r\n        \r\n        this._elem.addClass(klass);\r\n        \r\n        elem = plot.canvasManager.initCanvas(elem);\r\n        \r\n        elem = null;\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.GenericCanvas.prototype.setContext = function() {\r\n        this._ctx = this._elem.get(0).getContext(\"2d\");\r\n        return this._ctx;\r\n    };\r\n    \r\n    // Memory Leaks patch\r\n    $.jqplot.GenericCanvas.prototype.resetCanvas = function() {\r\n      if (this._elem) {\r\n        if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {\r\n           window.G_vmlCanvasManager.uninitElement(this._elem.get(0));\r\n        }\r\n        \r\n        //this._elem.remove();\r\n        this._elem.emptyForce();\r\n      }\r\n      \r\n      this._ctx = null;\r\n    };\r\n    \r\n    $.jqplot.HooksManager = function () {\r\n        this.hooks =[];\r\n        this.args = [];\r\n    };\r\n    \r\n    $.jqplot.HooksManager.prototype.addOnce = function(fn, args) {\r\n        args = args || [];\r\n        var havehook = false;\r\n        for (var i=0, l=this.hooks.length; i<l; i++) {\r\n            if (this.hooks[i] == fn) {\r\n                havehook = true;\r\n            }\r\n        }\r\n        if (!havehook) {\r\n            this.hooks.push(fn);\r\n            this.args.push(args);\r\n        }\r\n    };\r\n    \r\n    $.jqplot.HooksManager.prototype.add = function(fn, args) {\r\n        args = args || [];\r\n        this.hooks.push(fn);\r\n        this.args.push(args);\r\n    };\r\n    \r\n    $.jqplot.EventListenerManager = function () {\r\n        this.hooks =[];\r\n    };\r\n    \r\n    $.jqplot.EventListenerManager.prototype.addOnce = function(ev, fn) {\r\n        var havehook = false, h, i;\r\n        for (var i=0, l=this.hooks.length; i<l; i++) {\r\n            h = this.hooks[i];\r\n            if (h[0] == ev && h[1] == fn) {\r\n                havehook = true;\r\n            }\r\n        }\r\n        if (!havehook) {\r\n            this.hooks.push([ev, fn]);\r\n        }\r\n    };\r\n    \r\n    $.jqplot.EventListenerManager.prototype.add = function(ev, fn) {\r\n        this.hooks.push([ev, fn]);\r\n    };\r\n\r\n\r\n    var _axisNames = ['yMidAxis', 'xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis'];\r\n\r\n    /**\r\n     * Class: jqPlot\r\n     * Plot object returned by call to $.jqplot.  Handles parsing user options,\r\n     * creating sub objects (Axes, legend, title, series) and rendering the plot.\r\n     */\r\n    function jqPlot() {\r\n        // Group: Properties\r\n        // These properties are specified at the top of the options object\r\n        // like so:\r\n        // > {\r\n        // >     axesDefaults:{min:0},\r\n        // >     series:[{color:'#6633dd'}],\r\n        // >     title: 'A Plot'\r\n        // > }\r\n        //\r\n\r\n        // prop: animate\r\n        // True to animate the series on initial plot draw (renderer dependent).\r\n        // Actual animation functionality must be supported in the renderer.\r\n        this.animate = false;\r\n        // prop: animateReplot\r\n        // True to animate series after a call to the replot() method.\r\n        // Use with caution!  Replots can happen very frequently under\r\n        // certain circumstances (e.g. resizing, dragging points) and\r\n        // animation in these situations can cause problems.\r\n        this.animateReplot = false;\r\n        // prop: axes\r\n        // up to 4 axes are supported, each with its own options, \r\n        // See <Axis> for axis specific options.\r\n        this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis'), yMidAxis: new Axis('yMidAxis')};\r\n        this.baseCanvas = new $.jqplot.GenericCanvas();\r\n        // true to intercept right click events and fire a 'jqplotRightClick' event.\r\n        // this will also block the context menu.\r\n        this.captureRightClick = false;\r\n        // prop: data\r\n        // user's data.  Data should *NOT* be specified in the options object,\r\n        // but be passed in as the second argument to the $.jqplot() function.\r\n        // The data property is described here soley for reference. \r\n        // The data should be in the form of an array of 2D or 1D arrays like\r\n        // > [ [[x1, y1], [x2, y2],...], [y1, y2, ...] ].\r\n        this.data = [];\r\n        // prop: dataRenderer\r\n        // A callable which can be used to preprocess data passed into the plot.\r\n        // Will be called with 3 arguments: the plot data, a reference to the plot,\r\n        // and the value of dataRendererOptions.\r\n        this.dataRenderer;\r\n        // prop: dataRendererOptions\r\n        // Options that will be passed to the dataRenderer.\r\n        // Can be of any type.\r\n        this.dataRendererOptions;\r\n        this.defaults = {\r\n            // prop: axesDefaults\r\n            // default options that will be applied to all axes.\r\n            // see <Axis> for axes options.\r\n            axesDefaults: {},\r\n            axes: {xaxis:{}, yaxis:{}, x2axis:{}, y2axis:{}, y3axis:{}, y4axis:{}, y5axis:{}, y6axis:{}, y7axis:{}, y8axis:{}, y9axis:{}, yMidAxis:{}},\r\n            // prop: seriesDefaults\r\n            // default options that will be applied to all series.\r\n            // see <Series> for series options.\r\n            seriesDefaults: {},\r\n            series:[]\r\n        };\r\n        // prop: defaultAxisStart\r\n        // 1-D data series are internally converted into 2-D [x,y] data point arrays\r\n        // by jqPlot.  This is the default starting value for the missing x or y value.\r\n        // The added data will be a monotonically increasing series (e.g. [1, 2, 3, ...])\r\n        // starting at this value.\r\n        this.defaultAxisStart = 1;\r\n        // this.doCustomEventBinding = true;\r\n        // prop: drawIfHidden\r\n        // True to execute the draw method even if the plot target is hidden.\r\n        // Generally, this should be false.  Most plot elements will not be sized/\r\n        // positioned correclty if renderered into a hidden container.  To render into\r\n        // a hidden container, call the replot method when the container is shown.\r\n        this.drawIfHidden = false;\r\n        this.eventCanvas = new $.jqplot.GenericCanvas();\r\n        // prop: fillBetween\r\n        // Fill between 2 line series in a plot.\r\n        // Options object:\r\n        // {\r\n        //    series1: first index (0 based) of series in fill\r\n        //    series2: second index (0 based) of series in fill\r\n        //    color: color of fill [default fillColor of series1]\r\n        //    baseSeries:  fill will be drawn below this series (0 based index)\r\n        //    fill: false to turn off fill [default true].\r\n        //  }\r\n        this.fillBetween = {\r\n            series1: null,\r\n            series2: null,\r\n            color: null,\r\n            baseSeries: 0,\r\n            fill: true\r\n        };\r\n        // prop; fontFamily\r\n        // css spec for the font-family attribute.  Default for the entire plot.\r\n        this.fontFamily;\r\n        // prop: fontSize\r\n        // css spec for the font-size attribute.  Default for the entire plot.\r\n        this.fontSize;\r\n        // prop: grid\r\n        // See <Grid> for grid specific options.\r\n        this.grid = new Grid();\r\n        // prop: legend\r\n        // see <$.jqplot.TableLegendRenderer>\r\n        this.legend = new Legend();\r\n        // prop: noDataIndicator\r\n        // Options to set up a mock plot with a data loading indicator if no data is specified.\r\n        this.noDataIndicator = {    \r\n            show: false,\r\n            indicator: 'Loading Data...',\r\n            axes: {\r\n                xaxis: {\r\n                    min: 0,\r\n                    max: 10,\r\n                    tickInterval: 2,\r\n                    show: true\r\n                },\r\n                yaxis: {\r\n                    min: 0,\r\n                    max: 12,\r\n                    tickInterval: 3,\r\n                    show: true\r\n                }\r\n            }\r\n        };\r\n        // prop: negativeSeriesColors \r\n        // colors to use for portions of the line below zero.\r\n        this.negativeSeriesColors = $.jqplot.config.defaultNegativeColors;\r\n        // container to hold all of the merged options.  Convienence for plugins.\r\n        this.options = {};\r\n        this.previousSeriesStack = [];\r\n        // Namespace to hold plugins.  Generally non-renderer plugins add themselves to here.\r\n        this.plugins = {};\r\n        // prop: series\r\n        // Array of series object options.\r\n        // see <Series> for series specific options.\r\n        this.series = [];\r\n        // array of series indices. Keep track of order\r\n        // which series canvases are displayed, lowest\r\n        // to highest, back to front.\r\n        this.seriesStack = [];\r\n        // prop: seriesColors\r\n        // Ann array of CSS color specifications that will be applied, in order,\r\n        // to the series in the plot.  Colors will wrap around so, if their\r\n        // are more series than colors, colors will be reused starting at the\r\n        // beginning.  For pie charts, this specifies the colors of the slices.\r\n        this.seriesColors = $.jqplot.config.defaultColors;\r\n        // prop: sortData\r\n        // false to not sort the data passed in by the user.\r\n        // Many bar, stacked and other graphs as well as many plugins depend on\r\n        // having sorted data.\r\n        this.sortData = true;\r\n        // prop: stackSeries\r\n        // true or false, creates a stack or \"mountain\" plot.\r\n        // Not all series renderers may implement this option.\r\n        this.stackSeries = false;\r\n        // a shortcut for axis syncTicks options.  Not implemented yet.\r\n        this.syncXTicks = true;\r\n        // a shortcut for axis syncTicks options.  Not implemented yet.\r\n        this.syncYTicks = true;\r\n        // the jquery object for the dom target.\r\n        this.target = null; \r\n        // The id of the dom element to render the plot into\r\n        this.targetId = null;\r\n        // prop textColor\r\n        // css spec for the css color attribute.  Default for the entire plot.\r\n        this.textColor;\r\n        // prop: title\r\n        // Title object.  See <Title> for specific options.  As a shortcut, you\r\n        // can specify the title option as just a string like: title: 'My Plot'\r\n        // and this will create a new title object with the specified text.\r\n        this.title = new Title();\r\n        // Count how many times the draw method has been called while the plot is visible.\r\n        // Mostly used to test if plot has never been dran (=0), has been successfully drawn\r\n        // into a visible container once (=1) or draw more than once into a visible container.\r\n        // Can use this in tests to see if plot has been visibly drawn at least one time.\r\n        // After plot has been visibly drawn once, it generally doesn't need redrawing if its\r\n        // container is hidden and shown.\r\n        this._drawCount = 0;\r\n        // sum of y values for all series in plot.\r\n        // used in mekko chart.\r\n        this._sumy = 0;\r\n        this._sumx = 0;\r\n        // array to hold the cumulative stacked series data.\r\n        // used to ajust the individual series data, which won't have access to other\r\n        // series data.\r\n        this._stackData = [];\r\n        // array that holds the data to be plotted. This will be the series data\r\n        // merged with the the appropriate data from _stackData according to the stackAxis.\r\n        this._plotData = [];\r\n        this._width = null;\r\n        this._height = null; \r\n        this._plotDimensions = {height:null, width:null};\r\n        this._gridPadding = {top:null, right:null, bottom:null, left:null};\r\n        this._defaultGridPadding = {top:10, right:10, bottom:23, left:10};\r\n\r\n        this._addDomReference = $.jqplot.config.addDomReference;\r\n\r\n        this.preInitHooks = new $.jqplot.HooksManager();\r\n        this.postInitHooks = new $.jqplot.HooksManager();\r\n        this.preParseOptionsHooks = new $.jqplot.HooksManager();\r\n        this.postParseOptionsHooks = new $.jqplot.HooksManager();\r\n        this.preDrawHooks = new $.jqplot.HooksManager();\r\n        this.postDrawHooks = new $.jqplot.HooksManager();\r\n        this.preDrawSeriesHooks = new $.jqplot.HooksManager();\r\n        this.postDrawSeriesHooks = new $.jqplot.HooksManager();\r\n        this.preDrawLegendHooks = new $.jqplot.HooksManager();\r\n        this.addLegendRowHooks = new $.jqplot.HooksManager();\r\n        this.preSeriesInitHooks = new $.jqplot.HooksManager();\r\n        this.postSeriesInitHooks = new $.jqplot.HooksManager();\r\n        this.preParseSeriesOptionsHooks = new $.jqplot.HooksManager();\r\n        this.postParseSeriesOptionsHooks = new $.jqplot.HooksManager();\r\n        this.eventListenerHooks = new $.jqplot.EventListenerManager();\r\n        this.preDrawSeriesShadowHooks = new $.jqplot.HooksManager();\r\n        this.postDrawSeriesShadowHooks = new $.jqplot.HooksManager();\r\n        \r\n        this.colorGenerator = new $.jqplot.ColorGenerator();\r\n        this.negativeColorGenerator = new $.jqplot.ColorGenerator();\r\n\r\n        this.canvasManager = new $.jqplot.CanvasManager();\r\n\r\n        this.themeEngine = new $.jqplot.ThemeEngine();\r\n        \r\n        var seriesColorsIndex = 0;\r\n\r\n        // Group: methods\r\n        //\r\n        // method: init\r\n        // sets the plot target, checks data and applies user\r\n        // options to plot.\r\n        this.init = function(target, data, options) {\r\n            options = options || {};\r\n            for (var i=0; i<$.jqplot.preInitHooks.length; i++) {\r\n                $.jqplot.preInitHooks[i].call(this, target, data, options);\r\n            }\r\n\r\n            for (var i=0; i<this.preInitHooks.hooks.length; i++) {\r\n                this.preInitHooks.hooks[i].call(this, target, data, options);\r\n            }\r\n            \r\n            this.targetId = '#'+target;\r\n            this.target = $('#'+target);\r\n\r\n            //////\r\n            // Add a reference to plot\r\n            //////\r\n            if (this._addDomReference) {\r\n                this.target.data('jqplot', this);\r\n            }\r\n            // remove any error class that may be stuck on target.\r\n            this.target.removeClass('jqplot-error');\r\n            if (!this.target.get(0)) {\r\n                throw new Error(\"No plot target specified\");\r\n            }\r\n            \r\n            // make sure the target is positioned by some means and set css\r\n            if (this.target.css('position') == 'static') {\r\n                this.target.css('position', 'relative');\r\n            }\r\n            if (!this.target.hasClass('jqplot-target')) {\r\n                this.target.addClass('jqplot-target');\r\n            }\r\n            \r\n            // if no height or width specified, use a default.\r\n            if (!this.target.height()) {\r\n                var h;\r\n                if (options && options.height) {\r\n                    h = parseInt(options.height, 10);\r\n                }\r\n                else if (this.target.attr('data-height')) {\r\n                    h = parseInt(this.target.attr('data-height'), 10);\r\n                }\r\n                else {\r\n                    h = parseInt($.jqplot.config.defaultHeight, 10);\r\n                }\r\n                this._height = h;\r\n                this.target.css('height', h+'px');\r\n            }\r\n            else {\r\n                this._height = h = this.target.height();\r\n            }\r\n            if (!this.target.width()) {\r\n                var w;\r\n                if (options && options.width) {\r\n                    w = parseInt(options.width, 10);\r\n                }\r\n                else if (this.target.attr('data-width')) {\r\n                    w = parseInt(this.target.attr('data-width'), 10);\r\n                }\r\n                else {\r\n                    w = parseInt($.jqplot.config.defaultWidth, 10);\r\n                }\r\n                this._width = w;\r\n                this.target.css('width', w+'px');\r\n            }\r\n            else {\r\n                this._width = w = this.target.width();\r\n            }\r\n\r\n            for (var i=0, l=_axisNames.length; i<l; i++) {\r\n                this.axes[_axisNames[i]] = new Axis(_axisNames[i]);\r\n            }\r\n            \r\n            this._plotDimensions.height = this._height;\r\n            this._plotDimensions.width = this._width;\r\n            this.grid._plotDimensions = this._plotDimensions;\r\n            this.title._plotDimensions = this._plotDimensions;\r\n            this.baseCanvas._plotDimensions = this._plotDimensions;\r\n            this.eventCanvas._plotDimensions = this._plotDimensions;\r\n            this.legend._plotDimensions = this._plotDimensions;\r\n            if (this._height <=0 || this._width <=0 || !this._height || !this._width) {\r\n                throw new Error(\"Canvas dimension not set\");\r\n            }\r\n            \r\n            if (options.dataRenderer && $.isFunction(options.dataRenderer)) {\r\n                if (options.dataRendererOptions) {\r\n                    this.dataRendererOptions = options.dataRendererOptions;\r\n                }\r\n                this.dataRenderer = options.dataRenderer;\r\n                data = this.dataRenderer(data, this, this.dataRendererOptions);\r\n            }\r\n            \r\n            if (options.noDataIndicator && $.isPlainObject(options.noDataIndicator)) {\r\n                $.extend(true, this.noDataIndicator, options.noDataIndicator);\r\n            }\r\n            \r\n            if (data == null || $.isArray(data) == false || data.length == 0 || $.isArray(data[0]) == false || data[0].length == 0) {\r\n                \r\n                if (this.noDataIndicator.show == false) {\r\n                    throw new Error(\"No data specified\");\r\n                }\r\n                \r\n                else {\r\n                    // have to be descructive here in order for plot to not try and render series.\r\n                    // This means that $.jqplot() will have to be called again when there is data.\r\n                    //delete options.series;\r\n                    \r\n                    for (var ax in this.noDataIndicator.axes) {\r\n                        for (var prop in this.noDataIndicator.axes[ax]) {\r\n                            this.axes[ax][prop] = this.noDataIndicator.axes[ax][prop];\r\n                        }\r\n                    }\r\n                    \r\n                    this.postDrawHooks.add(function() {\r\n                        var eh = this.eventCanvas.getHeight();\r\n                        var ew = this.eventCanvas.getWidth();\r\n                        var temp = $('<div class=\"jqplot-noData-container\" style=\"position:absolute;\"></div>');\r\n                        this.target.append(temp);\r\n                        temp.height(eh);\r\n                        temp.width(ew);\r\n                        temp.css('top', this.eventCanvas._offsets.top);\r\n                        temp.css('left', this.eventCanvas._offsets.left);\r\n                        \r\n                        var temp2 = $('<div class=\"jqplot-noData-contents\" style=\"text-align:center; position:relative; margin-left:auto; margin-right:auto;\"></div>');\r\n                        temp.append(temp2);\r\n                        temp2.html(this.noDataIndicator.indicator);\r\n                        var th = temp2.height();\r\n                        var tw = temp2.width();\r\n                        temp2.height(th);\r\n                        temp2.width(tw);\r\n                        temp2.css('top', (eh - th)/2 + 'px');\r\n                    });\r\n\r\n                }\r\n            }\r\n            \r\n            // make a copy of the data\r\n            this.data = $.extend(true, [], data);\r\n            \r\n            this.parseOptions(options);\r\n            \r\n            if (this.textColor) {\r\n                this.target.css('color', this.textColor);\r\n            }\r\n            if (this.fontFamily) {\r\n                this.target.css('font-family', this.fontFamily);\r\n            }\r\n            if (this.fontSize) {\r\n                this.target.css('font-size', this.fontSize);\r\n            }\r\n            \r\n            this.title.init();\r\n            this.legend.init();\r\n            this._sumy = 0;\r\n            this._sumx = 0;\r\n            this.computePlotData();\r\n            for (var i=0; i<this.series.length; i++) {\r\n                // set default stacking order for series canvases\r\n                this.seriesStack.push(i);\r\n                this.previousSeriesStack.push(i);\r\n                this.series[i].shadowCanvas._plotDimensions = this._plotDimensions;\r\n                this.series[i].canvas._plotDimensions = this._plotDimensions;\r\n                for (var j=0; j<$.jqplot.preSeriesInitHooks.length; j++) {\r\n                    $.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                for (var j=0; j<this.preSeriesInitHooks.hooks.length; j++) {\r\n                    this.preSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                // this.populatePlotData(this.series[i], i);\r\n                this.series[i]._plotDimensions = this._plotDimensions;\r\n                this.series[i].init(i, this.grid.borderWidth, this);\r\n                for (var j=0; j<$.jqplot.postSeriesInitHooks.length; j++) {\r\n                    $.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                for (var j=0; j<this.postSeriesInitHooks.hooks.length; j++) {\r\n                    this.postSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                this._sumy += this.series[i]._sumy;\r\n                this._sumx += this.series[i]._sumx;\r\n            }\r\n\r\n            var name,\r\n                axis;\r\n            for (var i=0, l=_axisNames.length; i<l; i++) {\r\n                name = _axisNames[i];\r\n                axis = this.axes[name];\r\n                axis._plotDimensions = this._plotDimensions;\r\n                axis.init();\r\n                if (this.axes[name].borderColor == null) {\r\n                    if (name.charAt(0) !== 'x' && axis.useSeriesColor === true && axis.show) {\r\n                        axis.borderColor = axis._series[0].color;\r\n                    }\r\n                    else {\r\n                        axis.borderColor = this.grid.borderColor;\r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (this.sortData) {\r\n                sortData(this.series);\r\n            }\r\n            this.grid.init();\r\n            this.grid._axes = this.axes;\r\n            \r\n            this.legend._series = this.series;\r\n\r\n            for (var i=0; i<$.jqplot.postInitHooks.length; i++) {\r\n                $.jqplot.postInitHooks[i].call(this, target, this.data, options);\r\n            }\r\n\r\n            for (var i=0; i<this.postInitHooks.hooks.length; i++) {\r\n                this.postInitHooks.hooks[i].call(this, target, this.data, options);\r\n            }\r\n        };  \r\n        \r\n        // method: resetAxesScale\r\n        // Reset the specified axes min, max, numberTicks and tickInterval properties to null\r\n        // or reset these properties on all axes if no list of axes is provided.\r\n        //\r\n        // Parameters:\r\n        // axes - Boolean to reset or not reset all axes or an array or object of axis names to reset.\r\n        this.resetAxesScale = function(axes, options) {\r\n            var opts = options || {};\r\n            var ax = axes || this.axes;\r\n            if (ax === true) {\r\n                ax = this.axes;\r\n            }\r\n            if ($.isArray(ax)) {\r\n                for (var i = 0; i < ax.length; i++) {\r\n                    this.axes[ax[i]].resetScale(opts[ax[i]]);\r\n                }\r\n            }\r\n            else if (typeof(ax) === 'object') {\r\n                for (var name in ax) {\r\n                    this.axes[name].resetScale(opts[name]);\r\n                }\r\n            }\r\n        };\r\n        // method: reInitialize\r\n        // reinitialize plot for replotting.\r\n        // not called directly.\r\n        this.reInitialize = function (data, opts) {\r\n            // Plot should be visible and have a height and width.\r\n            // If plot doesn't have height and width for some\r\n            // reason, set it by other means.  Plot must not have\r\n            // a display:none attribute, however.\r\n\r\n            var options = $.extend(true, {}, this.options, opts);\r\n\r\n            var target = this.targetId.substr(1);\r\n            var tdata = (data == null) ? this.data : data;\r\n\r\n            for (var i=0; i<$.jqplot.preInitHooks.length; i++) {\r\n                $.jqplot.preInitHooks[i].call(this, target, tdata, options);\r\n            }\r\n\r\n            for (var i=0; i<this.preInitHooks.hooks.length; i++) {\r\n                this.preInitHooks.hooks[i].call(this, target, tdata, options);\r\n            }\r\n            \r\n            this._height = this.target.height();\r\n            this._width = this.target.width();\r\n            \r\n            if (this._height <=0 || this._width <=0 || !this._height || !this._width) {\r\n                throw new Error(\"Target dimension not set\");\r\n            }\r\n            \r\n            this._plotDimensions.height = this._height;\r\n            this._plotDimensions.width = this._width;\r\n            this.grid._plotDimensions = this._plotDimensions;\r\n            this.title._plotDimensions = this._plotDimensions;\r\n            this.baseCanvas._plotDimensions = this._plotDimensions;\r\n            this.eventCanvas._plotDimensions = this._plotDimensions;\r\n            this.legend._plotDimensions = this._plotDimensions;\r\n\r\n            var name,\r\n                t, \r\n                j, \r\n                axis;\r\n\r\n            for (var i=0, l=_axisNames.length; i<l; i++) {\r\n                name = _axisNames[i];\r\n                axis = this.axes[name];\r\n\r\n                // Memory Leaks patch : clear ticks elements\r\n                t = axis._ticks;\r\n                for (var j = 0, tlen = t.length; j < tlen; j++) {\r\n                  var el = t[j]._elem;\r\n                  if (el) {\r\n                    // if canvas renderer\r\n                    if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {\r\n                      window.G_vmlCanvasManager.uninitElement(el.get(0));\r\n                    }\r\n                    el.emptyForce();\r\n                    el = null;\r\n                    t._elem = null;\r\n                  }\r\n                }\r\n                t = null;\r\n\r\n                delete axis.ticks;\r\n                delete axis._ticks;\r\n                this.axes[name] = new Axis(name);\r\n                this.axes[name]._plotWidth = this._width;\r\n                this.axes[name]._plotHeight = this._height;\r\n            }\r\n            \r\n            if (data) {\r\n                if (options.dataRenderer && $.isFunction(options.dataRenderer)) {\r\n                    if (options.dataRendererOptions) {\r\n                        this.dataRendererOptions = options.dataRendererOptions;\r\n                    }\r\n                    this.dataRenderer = options.dataRenderer;\r\n                    data = this.dataRenderer(data, this, this.dataRendererOptions);\r\n                }\r\n                \r\n                // make a copy of the data\r\n                this.data = $.extend(true, [], data);\r\n            }\r\n\r\n            if (opts) {\r\n                this.parseOptions(options);\r\n            }\r\n            \r\n            this.title._plotWidth = this._width;\r\n            \r\n            if (this.textColor) {\r\n                this.target.css('color', this.textColor);\r\n            }\r\n            if (this.fontFamily) {\r\n                this.target.css('font-family', this.fontFamily);\r\n            }\r\n            if (this.fontSize) {\r\n                this.target.css('font-size', this.fontSize);\r\n            }\r\n\r\n            this.title.init();\r\n            this.legend.init();\r\n            this._sumy = 0;\r\n            this._sumx = 0;\r\n\r\n            this.seriesStack = [];\r\n            this.previousSeriesStack = [];\r\n\r\n            this.computePlotData();\r\n            for (var i=0, l=this.series.length; i<l; i++) {\r\n                // set default stacking order for series canvases\r\n                this.seriesStack.push(i);\r\n                this.previousSeriesStack.push(i);\r\n                this.series[i].shadowCanvas._plotDimensions = this._plotDimensions;\r\n                this.series[i].canvas._plotDimensions = this._plotDimensions;\r\n                for (var j=0; j<$.jqplot.preSeriesInitHooks.length; j++) {\r\n                    $.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                for (var j=0; j<this.preSeriesInitHooks.hooks.length; j++) {\r\n                    this.preSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                // this.populatePlotData(this.series[i], i);\r\n                this.series[i]._plotDimensions = this._plotDimensions;\r\n                this.series[i].init(i, this.grid.borderWidth, this);\r\n                for (var j=0; j<$.jqplot.postSeriesInitHooks.length; j++) {\r\n                    $.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                for (var j=0; j<this.postSeriesInitHooks.hooks.length; j++) {\r\n                    this.postSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this);\r\n                }\r\n                this._sumy += this.series[i]._sumy;\r\n                this._sumx += this.series[i]._sumx;\r\n            }\r\n\r\n            for (var i=0, l=_axisNames.length; i<l; i++) {\r\n                name = _axisNames[i];\r\n                axis = this.axes[name];\r\n\r\n                axis._plotDimensions = this._plotDimensions;\r\n                axis.init();\r\n                if (axis.borderColor == null) {\r\n                    if (name.charAt(0) !== 'x' && axis.useSeriesColor === true && axis.show) {\r\n                        axis.borderColor = axis._series[0].color;\r\n                    }\r\n                    else {\r\n                        axis.borderColor = this.grid.borderColor;\r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (this.sortData) {\r\n                sortData(this.series);\r\n            }\r\n            this.grid.init();\r\n            this.grid._axes = this.axes;\r\n            \r\n            this.legend._series = this.series;\r\n\r\n            for (var i=0, l=$.jqplot.postInitHooks.length; i<l; i++) {\r\n                $.jqplot.postInitHooks[i].call(this, target, this.data, options);\r\n            }\r\n\r\n            for (var i=0, l=this.postInitHooks.hooks.length; i<l; i++) {\r\n                this.postInitHooks.hooks[i].call(this, target, this.data, options);\r\n            }\r\n        };\r\n\r\n\r\n\r\n        // method: quickInit\r\n        // \r\n        // Quick reinitialization plot for replotting.\r\n        // Does not parse options ore recreate axes and series.\r\n        // not called directly.\r\n        this.quickInit = function () {\r\n            // Plot should be visible and have a height and width.\r\n            // If plot doesn't have height and width for some\r\n            // reason, set it by other means.  Plot must not have\r\n            // a display:none attribute, however.\r\n            \r\n            this._height = this.target.height();\r\n            this._width = this.target.width();\r\n            \r\n            if (this._height <=0 || this._width <=0 || !this._height || !this._width) {\r\n                throw new Error(\"Target dimension not set\");\r\n            }\r\n            \r\n            this._plotDimensions.height = this._height;\r\n            this._plotDimensions.width = this._width;\r\n            this.grid._plotDimensions = this._plotDimensions;\r\n            this.title._plotDimensions = this._plotDimensions;\r\n            this.baseCanvas._plotDimensions = this._plotDimensions;\r\n            this.eventCanvas._plotDimensions = this._plotDimensions;\r\n            this.legend._plotDimensions = this._plotDimensions;\r\n            \r\n            for (var n in this.axes) {\r\n                this.axes[n]._plotWidth = this._width;\r\n                this.axes[n]._plotHeight = this._height;\r\n            }\r\n            \r\n            this.title._plotWidth = this._width;\r\n            \r\n            if (this.textColor) {\r\n                this.target.css('color', this.textColor);\r\n            }\r\n            if (this.fontFamily) {\r\n                this.target.css('font-family', this.fontFamily);\r\n            }\r\n            if (this.fontSize) {\r\n                this.target.css('font-size', this.fontSize);\r\n            }\r\n            \r\n            this._sumy = 0;\r\n            this._sumx = 0;\r\n            this.computePlotData();\r\n            for (var i=0; i<this.series.length; i++) {\r\n                // this.populatePlotData(this.series[i], i);\r\n                if (this.series[i]._type === 'line' && this.series[i].renderer.bands.show) {\r\n                    this.series[i].renderer.initBands.call(this.series[i], this.series[i].renderer.options, this);\r\n                }\r\n                this.series[i]._plotDimensions = this._plotDimensions;\r\n                this.series[i].canvas._plotDimensions = this._plotDimensions;\r\n                //this.series[i].init(i, this.grid.borderWidth);\r\n                this._sumy += this.series[i]._sumy;\r\n                this._sumx += this.series[i]._sumx;\r\n            }\r\n\r\n            var name;\r\n            \r\n            for (var j=0; j<12; j++) {\r\n                name = _axisNames[j];\r\n                // Memory Leaks patch : clear ticks elements\r\n                var t = this.axes[name]._ticks;\r\n                for (var i = 0; i < t.length; i++) {\r\n                  var el = t[i]._elem;\r\n                  if (el) {\r\n                    // if canvas renderer\r\n                    if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {\r\n                      window.G_vmlCanvasManager.uninitElement(el.get(0));\r\n                    }\r\n                    el.emptyForce();\r\n                    el = null;\r\n                    t._elem = null;\r\n                  }\r\n                }\r\n                t = null;\r\n                \r\n                this.axes[name]._plotDimensions = this._plotDimensions;\r\n                this.axes[name]._ticks = [];\r\n                // this.axes[name].renderer.init.call(this.axes[name], {});\r\n            }\r\n            \r\n            if (this.sortData) {\r\n                sortData(this.series);\r\n            }\r\n            \r\n            this.grid._axes = this.axes;\r\n            \r\n            this.legend._series = this.series;\r\n        };\r\n        \r\n        // sort the series data in increasing order.\r\n        function sortData(series) {\r\n            var d, sd, pd, ppd, ret;\r\n            for (var i=0; i<series.length; i++) {\r\n                var check;\r\n                var bat = [series[i].data, series[i]._stackData, series[i]._plotData, series[i]._prevPlotData];\r\n                for (var n=0; n<4; n++) {\r\n                    check = true;\r\n                    d = bat[n];\r\n                    if (series[i]._stackAxis == 'x') {\r\n                        for (var j = 0; j < d.length; j++) {\r\n                            if (typeof(d[j][1]) != \"number\") {\r\n                                check = false;\r\n                                break;\r\n                            }\r\n                        }\r\n                        if (check) {\r\n                            d.sort(function(a,b) { return a[1] - b[1]; });\r\n                        }\r\n                    }\r\n                    else {\r\n                        for (var j = 0; j < d.length; j++) {\r\n                            if (typeof(d[j][0]) != \"number\") {\r\n                                check = false;\r\n                                break;\r\n                            }\r\n                        }\r\n                        if (check) {\r\n                            d.sort(function(a,b) { return a[0] - b[0]; });\r\n                        }\r\n                    }\r\n                }\r\n               \r\n            }\r\n        }\r\n\r\n        this.computePlotData = function() {\r\n            this._plotData = [];\r\n            this._stackData = [];\r\n            var series,\r\n                index,\r\n                l;\r\n\r\n\r\n            for (index=0, l=this.series.length; index<l; index++) {\r\n                series = this.series[index];\r\n                this._plotData.push([]);\r\n                this._stackData.push([]);\r\n                var cd = series.data;\r\n                this._plotData[index] = $.extend(true, [], cd);\r\n                this._stackData[index] = $.extend(true, [], cd);\r\n                series._plotData = this._plotData[index];\r\n                series._stackData = this._stackData[index];\r\n                var plotValues = {x:[], y:[]};\r\n\r\n                if (this.stackSeries && !series.disableStack) {\r\n                    series._stack = true;\r\n                    ///////////////////////////\r\n                    // have to check for nulls\r\n                    ///////////////////////////\r\n                    var sidx = (series._stackAxis === 'x') ? 0 : 1;\r\n\r\n                    for (var k=0, cdl=cd.length; k<cdl; k++) {\r\n                        var temp = cd[k][sidx];\r\n                        if (temp == null) {\r\n                            temp = 0;\r\n                        }\r\n                        this._plotData[index][k][sidx] = temp;\r\n                        this._stackData[index][k][sidx] = temp;\r\n\r\n                        if (index > 0) {\r\n                            for (var j=index; j--;) {\r\n                                var prevval = this._plotData[j][k][sidx];\r\n                                // only need to sum up the stack axis column of data\r\n                                // and only sum if it is of same sign.\r\n                                // if previous series isn't same sign, keep looking\r\n                                // at earlier series untill we find one of same sign.\r\n                                if (temp * prevval >= 0) {\r\n                                    this._plotData[index][k][sidx] += prevval;\r\n                                    this._stackData[index][k][sidx] += prevval;\r\n                                    break;\r\n                                } \r\n                            }\r\n                        }\r\n                    }\r\n\r\n                }\r\n                else {\r\n                    for (var i=0; i<series.data.length; i++) {\r\n                        plotValues.x.push(series.data[i][0]);\r\n                        plotValues.y.push(series.data[i][1]);\r\n                    }\r\n                    this._stackData.push(series.data);\r\n                    this.series[index]._stackData = series.data;\r\n                    this._plotData.push(series.data);\r\n                    series._plotData = series.data;\r\n                    series._plotValues = plotValues;\r\n                }\r\n                if (index>0) {\r\n                    series._prevPlotData = this.series[index-1]._plotData;\r\n                }\r\n                series._sumy = 0;\r\n                series._sumx = 0;\r\n                for (i=series.data.length-1; i>-1; i--) {\r\n                    series._sumy += series.data[i][1];\r\n                    series._sumx += series.data[i][0];\r\n                }\r\n            }\r\n\r\n        };\r\n        \r\n        // populate the _stackData and _plotData arrays for the plot and the series.\r\n        this.populatePlotData = function(series, index) {\r\n            // if a stacked chart, compute the stacked data\r\n            this._plotData = [];\r\n            this._stackData = [];\r\n            series._stackData = [];\r\n            series._plotData = [];\r\n            var plotValues = {x:[], y:[]};\r\n            if (this.stackSeries && !series.disableStack) {\r\n                series._stack = true;\r\n                var sidx = (series._stackAxis === 'x') ? 0 : 1;\r\n                // var idx = sidx ? 0 : 1;\r\n                // push the current data into stackData\r\n                //this._stackData.push(this.series[i].data);\r\n                var temp = $.extend(true, [], series.data);\r\n                // create the data that will be plotted for this series\r\n                var plotdata = $.extend(true, [], series.data);\r\n                var tempx, tempy, dval, stackval, comparator;\r\n                // for first series, nothing to add to stackData.\r\n                for (var j=0; j<index; j++) {\r\n                    var cd = this.series[j].data;\r\n                    for (var k=0; k<cd.length; k++) {\r\n                        dval = cd[k];\r\n                        tempx = (dval[0] != null) ? dval[0] : 0;\r\n                        tempy = (dval[1] != null) ? dval[1] : 0;\r\n                        temp[k][0] += tempx;\r\n                        temp[k][1] += tempy;\r\n                        stackval = (sidx) ? tempy : tempx;\r\n                        // only need to sum up the stack axis column of data\r\n                        // and only sum if it is of same sign.\r\n                        if (series.data[k][sidx] * stackval >= 0) {\r\n                            plotdata[k][sidx] += stackval;\r\n                        }\r\n                    }\r\n                }\r\n                for (var i=0; i<plotdata.length; i++) {\r\n                    plotValues.x.push(plotdata[i][0]);\r\n                    plotValues.y.push(plotdata[i][1]);\r\n                }\r\n                this._plotData.push(plotdata);\r\n                this._stackData.push(temp);\r\n                series._stackData = temp;\r\n                series._plotData = plotdata;\r\n                series._plotValues = plotValues;\r\n            }\r\n            else {\r\n                for (var i=0; i<series.data.length; i++) {\r\n                    plotValues.x.push(series.data[i][0]);\r\n                    plotValues.y.push(series.data[i][1]);\r\n                }\r\n                this._stackData.push(series.data);\r\n                this.series[index]._stackData = series.data;\r\n                this._plotData.push(series.data);\r\n                series._plotData = series.data;\r\n                series._plotValues = plotValues;\r\n            }\r\n            if (index>0) {\r\n                series._prevPlotData = this.series[index-1]._plotData;\r\n            }\r\n            series._sumy = 0;\r\n            series._sumx = 0;\r\n            for (i=series.data.length-1; i>-1; i--) {\r\n                series._sumy += series.data[i][1];\r\n                series._sumx += series.data[i][0];\r\n            }\r\n        };\r\n        \r\n        // function to safely return colors from the color array and wrap around at the end.\r\n        this.getNextSeriesColor = (function(t) {\r\n            var idx = 0;\r\n            var sc = t.seriesColors;\r\n            \r\n            return function () { \r\n                if (idx < sc.length) {\r\n                    return sc[idx++];\r\n                }\r\n                else {\r\n                    idx = 0;\r\n                    return sc[idx++];\r\n                }\r\n            };\r\n        })(this);\r\n    \r\n        this.parseOptions = function(options){\r\n            for (var i=0; i<this.preParseOptionsHooks.hooks.length; i++) {\r\n                this.preParseOptionsHooks.hooks[i].call(this, options);\r\n            }\r\n            for (var i=0; i<$.jqplot.preParseOptionsHooks.length; i++) {\r\n                $.jqplot.preParseOptionsHooks[i].call(this, options);\r\n            }\r\n            this.options = $.extend(true, {}, this.defaults, options);\r\n            var opts = this.options;\r\n            this.animate = opts.animate;\r\n            this.animateReplot = opts.animateReplot;\r\n            this.stackSeries = opts.stackSeries;\r\n            if ($.isPlainObject(opts.fillBetween)) {\r\n\r\n                var temp = ['series1', 'series2', 'color', 'baseSeries', 'fill'], \r\n                    tempi;\r\n\r\n                for (var i=0, l=temp.length; i<l; i++) {\r\n                    tempi = temp[i];\r\n                    if (opts.fillBetween[tempi] != null) {\r\n                        this.fillBetween[tempi] = opts.fillBetween[tempi];\r\n                    }\r\n                }\r\n            }\r\n\r\n            if (opts.seriesColors) {\r\n                this.seriesColors = opts.seriesColors;\r\n            }\r\n            if (opts.negativeSeriesColors) {\r\n                this.negativeSeriesColors = opts.negativeSeriesColors;\r\n            }\r\n            if (opts.captureRightClick) {\r\n                this.captureRightClick = opts.captureRightClick;\r\n            }\r\n            this.defaultAxisStart = (options && options.defaultAxisStart != null) ? options.defaultAxisStart : this.defaultAxisStart;\r\n            this.colorGenerator.setColors(this.seriesColors);\r\n            this.negativeColorGenerator.setColors(this.negativeSeriesColors);\r\n            // var cg = new this.colorGenerator(this.seriesColors);\r\n            // var ncg = new this.colorGenerator(this.negativeSeriesColors);\r\n            // this._gridPadding = this.options.gridPadding;\r\n            $.extend(true, this._gridPadding, opts.gridPadding);\r\n            this.sortData = (opts.sortData != null) ? opts.sortData : this.sortData;\r\n            for (var i=0; i<12; i++) {\r\n                var n = _axisNames[i];\r\n                var axis = this.axes[n];\r\n                axis._options = $.extend(true, {}, opts.axesDefaults, opts.axes[n]);\r\n                $.extend(true, axis, opts.axesDefaults, opts.axes[n]);\r\n                axis._plotWidth = this._width;\r\n                axis._plotHeight = this._height;\r\n            }\r\n            // if (this.data.length == 0) {\r\n            //     this.data = [];\r\n            //     for (var i=0; i<this.options.series.length; i++) {\r\n            //         this.data.push(this.options.series.data);\r\n            //     }    \r\n            // }\r\n                \r\n            var normalizeData = function(data, dir, start) {\r\n                // return data as an array of point arrays,\r\n                // in form [[x1,y1...], [x2,y2...], ...]\r\n                var temp = [];\r\n                var i, l;\r\n                dir = dir || 'vertical';\r\n                if (!$.isArray(data[0])) {\r\n                    // we have a series of scalars.  One line with just y values.\r\n                    // turn the scalar list of data into a data array of form:\r\n                    // [[1, data[0]], [2, data[1]], ...]\r\n                    for (i=0, l=data.length; i<l; i++) {\r\n                        if (dir == 'vertical') {\r\n                            temp.push([start + i, data[i]]);   \r\n                        }\r\n                        else {\r\n                            temp.push([data[i], start+i]);\r\n                        }\r\n                    }\r\n                }            \r\n                else {\r\n                    // we have a properly formatted data series, copy it.\r\n                    $.extend(true, temp, data);\r\n                }\r\n                return temp;\r\n            };\r\n\r\n            var colorIndex = 0;\r\n            this.series = [];\r\n            for (var i=0; i<this.data.length; i++) {\r\n                var sopts = $.extend(true, {index: i}, {seriesColors:this.seriesColors, negativeSeriesColors:this.negativeSeriesColors}, this.options.seriesDefaults, this.options.series[i], {rendererOptions:{animation:{show: this.animate}}});\r\n                // pass in options in case something needs set prior to initialization.\r\n                var temp = new Series(sopts);\r\n                for (var j=0; j<$.jqplot.preParseSeriesOptionsHooks.length; j++) {\r\n                    $.jqplot.preParseSeriesOptionsHooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]);\r\n                }\r\n                for (var j=0; j<this.preParseSeriesOptionsHooks.hooks.length; j++) {\r\n                    this.preParseSeriesOptionsHooks.hooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]);\r\n                }\r\n                // Now go back and apply the options to the series.  Really should just do this during initializaiton, but don't want to\r\n                // mess up preParseSeriesOptionsHooks at this point.\r\n                $.extend(true, temp, sopts);\r\n                var dir = 'vertical';\r\n                if (temp.renderer === $.jqplot.BarRenderer && temp.rendererOptions && temp.rendererOptions.barDirection == 'horizontal') {\r\n                    dir = 'horizontal';\r\n                    temp._stackAxis = 'x';\r\n                    temp._primaryAxis = '_yaxis';\r\n                }\r\n                temp.data = normalizeData(this.data[i], dir, this.defaultAxisStart);\r\n                switch (temp.xaxis) {\r\n                    case 'xaxis':\r\n                        temp._xaxis = this.axes.xaxis;\r\n                        break;\r\n                    case 'x2axis':\r\n                        temp._xaxis = this.axes.x2axis;\r\n                        break;\r\n                    default:\r\n                        break;\r\n                }\r\n                temp._yaxis = this.axes[temp.yaxis];\r\n                temp._xaxis._series.push(temp);\r\n                temp._yaxis._series.push(temp);\r\n                if (temp.show) {\r\n                    temp._xaxis.show = true;\r\n                    temp._yaxis.show = true;\r\n                }\r\n                else {\r\n                    if (temp._xaxis.scaleToHiddenSeries) {\r\n                        temp._xaxis.show = true;\r\n                    }\r\n                    if (temp._yaxis.scaleToHiddenSeries) {\r\n                        temp._yaxis.show = true;\r\n                    }\r\n                }\r\n\r\n                // // parse the renderer options and apply default colors if not provided\r\n                // if (!temp.color && temp.show != false) {\r\n                //     temp.color = cg.next();\r\n                //     colorIndex = cg.getIndex() - 1;;\r\n                // }\r\n                // if (!temp.negativeColor && temp.show != false) {\r\n                //     temp.negativeColor = ncg.get(colorIndex);\r\n                //     ncg.setIndex(colorIndex);\r\n                // }\r\n                if (!temp.label) {\r\n                    temp.label = 'Series '+ (i+1).toString();\r\n                }\r\n                // temp.rendererOptions.show = temp.show;\r\n                // $.extend(true, temp.renderer, {color:this.seriesColors[i]}, this.rendererOptions);\r\n                this.series.push(temp);  \r\n                for (var j=0; j<$.jqplot.postParseSeriesOptionsHooks.length; j++) {\r\n                    $.jqplot.postParseSeriesOptionsHooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]);\r\n                }\r\n                for (var j=0; j<this.postParseSeriesOptionsHooks.hooks.length; j++) {\r\n                    this.postParseSeriesOptionsHooks.hooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]);\r\n                }\r\n            }\r\n            \r\n            // copy the grid and title options into this object.\r\n            $.extend(true, this.grid, this.options.grid);\r\n            // if axis border properties aren't set, set default.\r\n            for (var i=0, l=_axisNames.length; i<l; i++) {\r\n                var n = _axisNames[i];\r\n                var axis = this.axes[n];\r\n                if (axis.borderWidth == null) {\r\n                    axis.borderWidth =this.grid.borderWidth;\r\n                }\r\n            }\r\n            \r\n            if (typeof this.options.title == 'string') {\r\n                this.title.text = this.options.title;\r\n            }\r\n            else if (typeof this.options.title == 'object') {\r\n                $.extend(true, this.title, this.options.title);\r\n            }\r\n            this.title._plotWidth = this._width;\r\n            this.legend.setOptions(this.options.legend);\r\n            \r\n            for (var i=0; i<$.jqplot.postParseOptionsHooks.length; i++) {\r\n                $.jqplot.postParseOptionsHooks[i].call(this, options);\r\n            }\r\n            for (var i=0; i<this.postParseOptionsHooks.hooks.length; i++) {\r\n                this.postParseOptionsHooks.hooks[i].call(this, options);\r\n            }\r\n        };\r\n        \r\n        // method: destroy\r\n        // Releases all resources occupied by the plot\r\n        this.destroy = function() {\r\n            this.canvasManager.freeAllCanvases();\r\n            if (this.eventCanvas && this.eventCanvas._elem) {\r\n                this.eventCanvas._elem.unbind();\r\n            }\r\n            // Couple of posts on Stack Overflow indicate that empty() doesn't\r\n            // always cear up the dom and release memory.  Sometimes setting\r\n            // innerHTML property to null is needed.  Particularly on IE, may \r\n            // have to directly set it to null, bypassing $.\r\n            this.target.empty();\r\n\r\n            this.target[0].innerHTML = '';\r\n        };\r\n        \r\n        // method: replot\r\n        // Does a reinitialization of the plot followed by\r\n        // a redraw.  Method could be used to interactively\r\n        // change plot characteristics and then replot.\r\n        //\r\n        // Parameters:\r\n        // options - Options used for replotting.\r\n        //\r\n        // Properties:\r\n        // clear - false to not clear (empty) the plot container before replotting (default: true).\r\n        // resetAxes - true to reset all axes min, max, numberTicks and tickInterval setting so axes will rescale themselves.\r\n        //             optionally pass in list of axes to reset (e.g. ['xaxis', 'y2axis']) (default: false).\r\n        this.replot = function(options) {\r\n            var opts =  options || {};\r\n            var data = opts.data || null;\r\n            var clear = (opts.clear === false) ? false : true;\r\n            var resetAxes = opts.resetAxes || false;\r\n            delete opts.data;\r\n            delete opts.clear;\r\n            delete opts.resetAxes;\r\n\r\n            this.target.trigger('jqplotPreReplot');\r\n            \r\n            if (clear) {\r\n                this.destroy();\r\n            }\r\n            // if have data or other options, full reinit.\r\n            // otherwise, quickinit.\r\n            if (data || !$.isEmptyObject(opts)) {\r\n                this.reInitialize(data, opts);\r\n            }\r\n            else {\r\n                this.quickInit();\r\n            }\r\n\r\n            if (resetAxes) {\r\n                this.resetAxesScale(resetAxes, opts.axes);\r\n            }\r\n            this.draw();\r\n            this.target.trigger('jqplotPostReplot');\r\n        };\r\n        \r\n        // method: redraw\r\n        // Empties the plot target div and redraws the plot.\r\n        // This enables plot data and properties to be changed\r\n        // and then to comletely clear the plot and redraw.\r\n        // redraw *will not* reinitialize any plot elements.\r\n        // That is, axes will not be autoscaled and defaults\r\n        // will not be reapplied to any plot elements.  redraw\r\n        // is used primarily with zooming. \r\n        //\r\n        // Parameters:\r\n        // clear - false to not clear (empty) the plot container before redrawing (default: true).\r\n        this.redraw = function(clear) {\r\n            clear = (clear != null) ? clear : true;\r\n            this.target.trigger('jqplotPreRedraw');\r\n            if (clear) {\r\n                this.canvasManager.freeAllCanvases();\r\n                this.eventCanvas._elem.unbind();\r\n                // Dont think I bind any events to the target, this shouldn't be necessary.\r\n                // It will remove user's events.\r\n                // this.target.unbind();\r\n                this.target.empty();\r\n            }\r\n             for (var ax in this.axes) {\r\n                this.axes[ax]._ticks = [];\r\n            }\r\n            this.computePlotData();\r\n            // for (var i=0; i<this.series.length; i++) {\r\n            //     this.populatePlotData(this.series[i], i);\r\n            // }\r\n            this._sumy = 0;\r\n            this._sumx = 0;\r\n            for (var i=0, tsl = this.series.length; i<tsl; i++) {\r\n                this._sumy += this.series[i]._sumy;\r\n                this._sumx += this.series[i]._sumx;\r\n            }\r\n            this.draw();\r\n            this.target.trigger('jqplotPostRedraw');\r\n        };\r\n        \r\n        // method: draw\r\n        // Draws all elements of the plot into the container.\r\n        // Does not clear the container before drawing.\r\n        this.draw = function(){\r\n            if (this.drawIfHidden || this.target.is(':visible')) {\r\n                this.target.trigger('jqplotPreDraw');\r\n                var i,\r\n                    j,\r\n                    l,\r\n                    tempseries;\r\n                for (i=0, l=$.jqplot.preDrawHooks.length; i<l; i++) {\r\n                    $.jqplot.preDrawHooks[i].call(this);\r\n                }\r\n                for (i=0, l=this.preDrawHooks.hooks.length; i<l; i++) {\r\n                    this.preDrawHooks.hooks[i].apply(this, this.preDrawSeriesHooks.args[i]);\r\n                }\r\n                // create an underlying canvas to be used for special features.\r\n                this.target.append(this.baseCanvas.createElement({left:0, right:0, top:0, bottom:0}, 'jqplot-base-canvas', null, this));\r\n                this.baseCanvas.setContext();\r\n                this.target.append(this.title.draw());\r\n                this.title.pack({top:0, left:0});\r\n                \r\n                // make room  for the legend between the grid and the edge.\r\n                // pass a dummy offsets object and a reference to the plot.\r\n                var legendElem = this.legend.draw({}, this);\r\n                \r\n                var gridPadding = {top:0, left:0, bottom:0, right:0};\r\n                \r\n                if (this.legend.placement == \"outsideGrid\") {\r\n                    // temporarily append the legend to get dimensions\r\n                    this.target.append(legendElem);\r\n                    switch (this.legend.location) {\r\n                        case 'n':\r\n                            gridPadding.top += this.legend.getHeight();\r\n                            break;\r\n                        case 's':\r\n                            gridPadding.bottom += this.legend.getHeight();\r\n                            break;\r\n                        case 'ne':\r\n                        case 'e':\r\n                        case 'se':\r\n                            gridPadding.right += this.legend.getWidth();\r\n                            break;\r\n                        case 'nw':\r\n                        case 'w':\r\n                        case 'sw':\r\n                            gridPadding.left += this.legend.getWidth();\r\n                            break;\r\n                        default:  // same as 'ne'\r\n                            gridPadding.right += this.legend.getWidth();\r\n                            break;\r\n                    }\r\n                    legendElem = legendElem.detach();\r\n                }\r\n                \r\n                var ax = this.axes;\r\n                var name;\r\n                // draw the yMidAxis first, so xaxis of pyramid chart can adjust itself if needed.\r\n                for (i=0; i<12; i++) {\r\n                    name = _axisNames[i];\r\n                    this.target.append(ax[name].draw(this.baseCanvas._ctx, this));\r\n                    ax[name].set();\r\n                }\r\n                if (ax.yaxis.show) {\r\n                    gridPadding.left += ax.yaxis.getWidth();\r\n                }\r\n                var ra = ['y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis'];\r\n                var rapad = [0, 0, 0, 0, 0, 0, 0, 0];\r\n                var gpr = 0;\r\n                var n;\r\n                for (n=0; n<8; n++) {\r\n                    if (ax[ra[n]].show) {\r\n                        gpr += ax[ra[n]].getWidth();\r\n                        rapad[n] = gpr;\r\n                    }\r\n                }\r\n                gridPadding.right += gpr;\r\n                if (ax.x2axis.show) {\r\n                    gridPadding.top += ax.x2axis.getHeight();\r\n                }\r\n                if (this.title.show) {\r\n                    gridPadding.top += this.title.getHeight();\r\n                }\r\n                if (ax.xaxis.show) {\r\n                    gridPadding.bottom += ax.xaxis.getHeight();\r\n                }\r\n                \r\n                // end of gridPadding adjustments.\r\n\r\n                // if user passed in gridDimensions option, check against calculated gridPadding\r\n                if (this.options.gridDimensions && $.isPlainObject(this.options.gridDimensions)) {\r\n                    var gdw = parseInt(this.options.gridDimensions.width, 10) || 0;\r\n                    var gdh = parseInt(this.options.gridDimensions.height, 10) || 0;\r\n                    var widthAdj = (this._width - gridPadding.left - gridPadding.right - gdw)/2;\r\n                    var heightAdj = (this._height - gridPadding.top - gridPadding.bottom - gdh)/2;\r\n\r\n                    if (heightAdj >= 0 && widthAdj >= 0) {\r\n                        gridPadding.top += heightAdj;\r\n                        gridPadding.bottom += heightAdj;\r\n                        gridPadding.left += widthAdj;\r\n                        gridPadding.right += widthAdj;\r\n                    }\r\n                }\r\n                var arr = ['top', 'bottom', 'left', 'right'];\r\n                for (var n in arr) {\r\n                    if (this._gridPadding[arr[n]] == null && gridPadding[arr[n]] > 0) {\r\n                        this._gridPadding[arr[n]] = gridPadding[arr[n]];\r\n                    }\r\n                    else if (this._gridPadding[arr[n]] == null) {\r\n                        this._gridPadding[arr[n]] = this._defaultGridPadding[arr[n]];\r\n                    }\r\n                }\r\n                \r\n                var legendPadding = this._gridPadding;\r\n                \r\n                if (this.legend.placement === 'outsideGrid') {\r\n                    legendPadding = {top:this.title.getHeight(), left: 0, right: 0, bottom: 0};\r\n                    if (this.legend.location === 's') {\r\n                        legendPadding.left = this._gridPadding.left;\r\n                        legendPadding.right = this._gridPadding.right;\r\n                    }\r\n                }\r\n                \r\n                ax.xaxis.pack({position:'absolute', bottom:this._gridPadding.bottom - ax.xaxis.getHeight(), left:0, width:this._width}, {min:this._gridPadding.left, max:this._width - this._gridPadding.right});\r\n                ax.yaxis.pack({position:'absolute', top:0, left:this._gridPadding.left - ax.yaxis.getWidth(), height:this._height}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top});\r\n                ax.x2axis.pack({position:'absolute', top:this._gridPadding.top - ax.x2axis.getHeight(), left:0, width:this._width}, {min:this._gridPadding.left, max:this._width - this._gridPadding.right});\r\n                for (i=8; i>0; i--) {\r\n                    ax[ra[i-1]].pack({position:'absolute', top:0, right:this._gridPadding.right - rapad[i-1]}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top});\r\n                }\r\n                var ltemp = (this._width - this._gridPadding.left - this._gridPadding.right)/2.0 + this._gridPadding.left - ax.yMidAxis.getWidth()/2.0;\r\n                ax.yMidAxis.pack({position:'absolute', top:0, left:ltemp, zIndex:9, textAlign: 'center'}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top});\r\n            \r\n                this.target.append(this.grid.createElement(this._gridPadding, this));\r\n                this.grid.draw();\r\n                \r\n                var series = this.series;\r\n                var seriesLength = series.length;\r\n                // put the shadow canvases behind the series canvases so shadows don't overlap on stacked bars.\r\n                for (i=0, l=seriesLength; i<l; i++) {\r\n                    // draw series in order of stacking.  This affects only\r\n                    // order in which canvases are added to dom.\r\n                    j = this.seriesStack[i];\r\n                    this.target.append(series[j].shadowCanvas.createElement(this._gridPadding, 'jqplot-series-shadowCanvas', null, this));\r\n                    series[j].shadowCanvas.setContext();\r\n                    series[j].shadowCanvas._elem.data('seriesIndex', j);\r\n                }\r\n                \r\n                for (i=0, l=seriesLength; i<l; i++) {\r\n                    // draw series in order of stacking.  This affects only\r\n                    // order in which canvases are added to dom.\r\n                    j = this.seriesStack[i];\r\n                    this.target.append(series[j].canvas.createElement(this._gridPadding, 'jqplot-series-canvas', null, this));\r\n                    series[j].canvas.setContext();\r\n                    series[j].canvas._elem.data('seriesIndex', j);\r\n                }\r\n                // Need to use filled canvas to capture events in IE.\r\n                // Also, canvas seems to block selection of other elements in document on FF.\r\n                this.target.append(this.eventCanvas.createElement(this._gridPadding, 'jqplot-event-canvas', null, this));\r\n                this.eventCanvas.setContext();\r\n                this.eventCanvas._ctx.fillStyle = 'rgba(0,0,0,0)';\r\n                this.eventCanvas._ctx.fillRect(0,0,this.eventCanvas._ctx.canvas.width, this.eventCanvas._ctx.canvas.height);\r\n            \r\n                // bind custom event handlers to regular events.\r\n                this.bindCustomEvents();\r\n            \r\n                // draw legend before series if the series needs to know the legend dimensions.\r\n                if (this.legend.preDraw) {  \r\n                    this.eventCanvas._elem.before(legendElem);\r\n                    this.legend.pack(legendPadding);\r\n                    if (this.legend._elem) {\r\n                        this.drawSeries({legendInfo:{location:this.legend.location, placement:this.legend.placement, width:this.legend.getWidth(), height:this.legend.getHeight(), xoffset:this.legend.xoffset, yoffset:this.legend.yoffset}});\r\n                    }\r\n                    else {\r\n                        this.drawSeries();\r\n                    }\r\n                }\r\n                else {  // draw series before legend\r\n                    this.drawSeries();\r\n                    if (seriesLength) {\r\n                        $(series[seriesLength-1].canvas._elem).after(legendElem);\r\n                    }\r\n                    this.legend.pack(legendPadding);                \r\n                }\r\n            \r\n                // register event listeners on the overlay canvas\r\n                for (var i=0, l=$.jqplot.eventListenerHooks.length; i<l; i++) {\r\n                    // in the handler, this will refer to the eventCanvas dom element.\r\n                    // make sure there are references back into plot objects.\r\n                    this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);\r\n                }\r\n            \r\n                // register event listeners on the overlay canvas\r\n                for (var i=0, l=this.eventListenerHooks.hooks.length; i<l; i++) {\r\n                    // in the handler, this will refer to the eventCanvas dom element.\r\n                    // make sure there are references back into plot objects.\r\n                    this.eventCanvas._elem.bind(this.eventListenerHooks.hooks[i][0], {plot:this}, this.eventListenerHooks.hooks[i][1]);\r\n                }\r\n\r\n                var fb = this.fillBetween;\r\n                if(typeof fb.series1 == 'number'){\r\n                    if(fb.fill&&fb.series1!==fb.series2&&fb.series1<seriesLength&&fb.series2<seriesLength&&series[fb.series1]._type===\"line\"&&series[fb.series2]._type===\"line\")\r\n                    this.doFillBetweenLines();\r\n                }\r\n                else{\r\n                    if(fb.series1 != null && fb.series2 != null){\r\n                        var doFb = false;\r\n                        if(fb.series1.length === fb.series2.length){\r\n                            var tempSeries1 = 0;\r\n                            var tempSeries2 = 0;\r\n                            \r\n                            for(var cnt = 0; cnt < fb.series1.length; cnt++){\r\n                                tempSeries1 = fb.series1[cnt];\r\n                                tempSeries2 = fb.series2[cnt];\r\n                                if(tempSeries1!==tempSeries2&&tempSeries1<seriesLength&&tempSeries2<seriesLength&&series[tempSeries1]._type===\"line\"&&series[tempSeries2]._type===\"line\"){\r\n                                    doFb = true;\r\n                                }\r\n                                else{\r\n                                    doFb = false;\r\n                                    break;\r\n                                }\r\n                            }\r\n                        }\r\n                        if(fb.fill && doFb){\r\n                            this.doFillBetweenLines();\r\n                        }\r\n                    }\r\n                }\r\n\r\n                for (var i=0, l=$.jqplot.postDrawHooks.length; i<l; i++) {\r\n                    $.jqplot.postDrawHooks[i].call(this);\r\n                }\r\n\r\n                for (var i=0, l=this.postDrawHooks.hooks.length; i<l; i++) {\r\n                    this.postDrawHooks.hooks[i].apply(this, this.postDrawHooks.args[i]);\r\n                }\r\n            \r\n                if (this.target.is(':visible')) {\r\n                    this._drawCount += 1;\r\n                }\r\n\r\n                var temps, \r\n                    tempr,\r\n                    sel,\r\n                    _els;\r\n                // ughh.  ideally would hide all series then show them.\r\n                for (i=0, l=seriesLength; i<l; i++) {\r\n                    temps = series[i];\r\n                    tempr = temps.renderer;\r\n                    sel = '.jqplot-point-label.jqplot-series-'+i;\r\n                    if (tempr.animation && tempr.animation._supported && tempr.animation.show && (this._drawCount < 2 || this.animateReplot)) {\r\n                        _els = this.target.find(sel);\r\n                        _els.stop(true, true).hide();\r\n                        temps.canvas._elem.stop(true, true).hide();\r\n                        temps.shadowCanvas._elem.stop(true, true).hide();\r\n                        temps.canvas._elem.jqplotEffect('blind', {mode: 'show', direction: tempr.animation.direction}, tempr.animation.speed);\r\n                        temps.shadowCanvas._elem.jqplotEffect('blind', {mode: 'show', direction: tempr.animation.direction}, tempr.animation.speed);\r\n                        _els.fadeIn(tempr.animation.speed*0.8);\r\n                    }\r\n                }\r\n                _els = null;\r\n            \r\n                this.target.trigger('jqplotPostDraw', [this]);\r\n            }\r\n        };\r\n\r\n        jqPlot.prototype.doFillBetweenLines = function () {\r\n            var fb = this.fillBetween;\r\n            var series = this.series;\r\n            var sid1 = fb.series1;\r\n            var sid2 = fb.series2;\r\n            var id1 = 0, id2 = 0;\r\n\r\n            function fill(id1, id2){\r\n                var series1 = series[id1];\r\n                var series2 = series[id2];\r\n                if (series2.renderer.smooth)\r\n                    var tempgd = series2.renderer._smoothedData.slice(0).reverse();\r\n                else\r\n                    var tempgd = series2.gridData.slice(0).reverse();\r\n                if (series1.renderer.smooth)\r\n                    var gd = series1.renderer._smoothedData.concat(tempgd);\r\n                else\r\n                    var gd = series1.gridData.concat(tempgd);\r\n                var color = fb.color !== null ? fb.color : series[sid1].fillColor;\r\n                var baseSeries = fb.baseSeries !== null ? fb.baseSeries : id1;\r\n                var sr =\r\n                    series[baseSeries].renderer.shapeRenderer;\r\n                var opts =\r\n                {\r\n                    fillStyle : color,\r\n                    fill : true,\r\n                    closePath : true\r\n                };\r\n                sr.draw(series1.shadowCanvas._ctx, gd, opts)\r\n            }\r\n\r\n            if(typeof sid1 == 'number' && typeof sid2 == 'number'){\r\n                id1 = sid1 < sid2 ? sid1 : sid2;\r\n                id2 = sid2 > sid1 ? sid2 : sid1;\r\n                fill(id1, id2);\r\n            }\r\n            else{\r\n                for(var cnt = 0; cnt < sid1.length ; cnt++){\r\n                    id1 = sid1[cnt] < sid2[cnt] ? sid1[cnt] : sid2[cnt];\r\n                    id2 = sid2[cnt] > sid1[cnt] ? sid2[cnt] : sid1[cnt];\r\n                    fill(id1, id2);\r\n                }\r\n            }\r\n        };\r\n        \r\n        this.bindCustomEvents = function() {\r\n            this.eventCanvas._elem.bind('click', {plot:this}, this.onClick);\r\n            this.eventCanvas._elem.bind('dblclick', {plot:this}, this.onDblClick);\r\n            this.eventCanvas._elem.bind('mousedown', {plot:this}, this.onMouseDown);\r\n            this.eventCanvas._elem.bind('mousemove', {plot:this}, this.onMouseMove);\r\n            this.eventCanvas._elem.bind('mouseenter', {plot:this}, this.onMouseEnter);\r\n            this.eventCanvas._elem.bind('mouseleave', {plot:this}, this.onMouseLeave);\r\n            if (this.captureRightClick) {\r\n                this.eventCanvas._elem.bind('mouseup', {plot:this}, this.onRightClick);\r\n                this.eventCanvas._elem.get(0).oncontextmenu = function() {\r\n                    return false;\r\n                };\r\n            }\r\n            else {\r\n                this.eventCanvas._elem.bind('mouseup', {plot:this}, this.onMouseUp);\r\n            }\r\n        };\r\n        \r\n        function getEventPosition(ev) {\r\n            var plot = ev.data.plot;\r\n            var go = plot.eventCanvas._elem.offset();\r\n            var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top};\r\n            var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null, yMidAxis:null};\r\n            var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis'];\r\n            var ax = plot.axes;\r\n            var n, axis;\r\n            for (n=11; n>0; n--) {\r\n                axis = an[n-1];\r\n                if (ax[axis].show) {\r\n                    dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]);\r\n                }\r\n            }\r\n\r\n            return {offsets:go, gridPos:gridPos, dataPos:dataPos};\r\n        }\r\n        \r\n        \r\n        // function to check if event location is over a area area\r\n        function checkIntersection(gridpos, plot) {\r\n            var series = plot.series;\r\n            var i, j, k, s, r, x, y, theta, sm, sa, minang, maxang;\r\n            var d0, d, p, pp, points, bw, hp;\r\n            var threshold, t;\r\n            for (k=plot.seriesStack.length-1; k>=0; k--) {\r\n                i = plot.seriesStack[k];\r\n                s = series[i];\r\n                hp = s._highlightThreshold;\r\n                switch (s.renderer.constructor) {\r\n                    case $.jqplot.BarRenderer:\r\n                        x = gridpos.x;\r\n                        y = gridpos.y;\r\n                        for (j=0; j<s._barPoints.length; j++) {\r\n                            points = s._barPoints[j];\r\n                            p = s.gridData[j];\r\n                            if (x>points[0][0] && x<points[2][0] && (y>points[2][1] && y<points[0][1] || y<points[2][1] && y>points[0][1])) {\r\n                                return {seriesIndex:s.index, pointIndex:j, gridData:p, data:s.data[j], points:s._barPoints[j]};\r\n                            }\r\n                        }\r\n                        break;\r\n                    case $.jqplot.PyramidRenderer:\r\n                        x = gridpos.x;\r\n                        y = gridpos.y;\r\n                        for (j=0; j<s._barPoints.length; j++) {\r\n                            points = s._barPoints[j];\r\n                            p = s.gridData[j];\r\n                            if (x > points[0][0] + hp[0][0] && x < points[2][0] + hp[2][0] && y > points[2][1] && y < points[0][1]) {\r\n                                return {seriesIndex:s.index, pointIndex:j, gridData:p, data:s.data[j], points:s._barPoints[j]};\r\n                            }\r\n                        }\r\n                        break;\r\n                    \r\n                    case $.jqplot.DonutRenderer:\r\n                        sa = s.startAngle/180*Math.PI;\r\n                        x = gridpos.x - s._center[0];\r\n                        y = gridpos.y - s._center[1];\r\n                        r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));\r\n                        if (x > 0 && -y >= 0) {\r\n                            theta = 2*Math.PI - Math.atan(-y/x);\r\n                        }\r\n                        else if (x > 0 && -y < 0) {\r\n                            theta = -Math.atan(-y/x);\r\n                        }\r\n                        else if (x < 0) {\r\n                            theta = Math.PI - Math.atan(-y/x);\r\n                        }\r\n                        else if (x == 0 && -y > 0) {\r\n                            theta = 3*Math.PI/2;\r\n                        }\r\n                        else if (x == 0 && -y < 0) {\r\n                            theta = Math.PI/2;\r\n                        }\r\n                        else if (x == 0 && y == 0) {\r\n                            theta = 0;\r\n                        }\r\n                        if (sa) {\r\n                            theta -= sa;\r\n                            if (theta < 0) {\r\n                                theta += 2*Math.PI;\r\n                            }\r\n                            else if (theta > 2*Math.PI) {\r\n                                theta -= 2*Math.PI;\r\n                            }\r\n                        }\r\n            \r\n                        sm = s.sliceMargin/180*Math.PI;\r\n                        if (r < s._radius && r > s._innerRadius) {\r\n                            for (j=0; j<s.gridData.length; j++) {\r\n                                minang = (j>0) ? s.gridData[j-1][1]+sm : sm;\r\n                                maxang = s.gridData[j][1];\r\n                                if (theta > minang && theta < maxang) {\r\n                                    return {seriesIndex:s.index, pointIndex:j, gridData:[gridpos.x,gridpos.y], data:s.data[j]};\r\n                                }\r\n                            }\r\n                        }\r\n                        break;\r\n                        \r\n                    case $.jqplot.PieRenderer:\r\n                        sa = s.startAngle/180*Math.PI;\r\n                        x = gridpos.x - s._center[0];\r\n                        y = gridpos.y - s._center[1];\r\n                        r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));\r\n                        if (x > 0 && -y >= 0) {\r\n                            theta = 2*Math.PI - Math.atan(-y/x);\r\n                        }\r\n                        else if (x > 0 && -y < 0) {\r\n                            theta = -Math.atan(-y/x);\r\n                        }\r\n                        else if (x < 0) {\r\n                            theta = Math.PI - Math.atan(-y/x);\r\n                        }\r\n                        else if (x == 0 && -y > 0) {\r\n                            theta = 3*Math.PI/2;\r\n                        }\r\n                        else if (x == 0 && -y < 0) {\r\n                            theta = Math.PI/2;\r\n                        }\r\n                        else if (x == 0 && y == 0) {\r\n                            theta = 0;\r\n                        }\r\n                        if (sa) {\r\n                            theta -= sa;\r\n                            if (theta < 0) {\r\n                                theta += 2*Math.PI;\r\n                            }\r\n                            else if (theta > 2*Math.PI) {\r\n                                theta -= 2*Math.PI;\r\n                            }\r\n                        }\r\n            \r\n                        sm = s.sliceMargin/180*Math.PI;\r\n                        if (r < s._radius) {\r\n                            for (j=0; j<s.gridData.length; j++) {\r\n                                minang = (j>0) ? s.gridData[j-1][1]+sm : sm;\r\n                                maxang = s.gridData[j][1];\r\n                                if (theta > minang && theta < maxang) {\r\n                                    return {seriesIndex:s.index, pointIndex:j, gridData:[gridpos.x,gridpos.y], data:s.data[j]};\r\n                                }\r\n                            }\r\n                        }\r\n                        break;\r\n                        \r\n                    case $.jqplot.BubbleRenderer:\r\n                        x = gridpos.x;\r\n                        y = gridpos.y;\r\n                        var ret = null;\r\n                        \r\n                        if (s.show) {\r\n                            for (var j=0; j<s.gridData.length; j++) {\r\n                                p = s.gridData[j];\r\n                                d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) );\r\n                                if (d <= p[2] && (d <= d0 || d0 == null)) {\r\n                                   d0 = d;\r\n                                   ret = {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                }\r\n                            }\r\n                            if (ret != null) {\r\n                                return ret;\r\n                            }\r\n                        }\r\n                        break;\r\n                        \r\n                    case $.jqplot.FunnelRenderer:\r\n                        x = gridpos.x;\r\n                        y = gridpos.y;\r\n                        var v = s._vertices,\r\n                            vfirst = v[0],\r\n                            vlast = v[v.length-1],\r\n                            lex,\r\n                            rex,\r\n                            cv;\r\n    \r\n                        // equations of right and left sides, returns x, y values given height of section (y value and 2 points)\r\n    \r\n                        function findedge (l, p1 , p2) {\r\n                            var m = (p1[1] - p2[1])/(p1[0] - p2[0]);\r\n                            var b = p1[1] - m*p1[0];\r\n                            var y = l + p1[1];\r\n        \r\n                            return [(y - b)/m, y];\r\n                        }\r\n    \r\n                        // check each section\r\n                        lex = findedge(y, vfirst[0], vlast[3]);\r\n                        rex = findedge(y, vfirst[1], vlast[2]);\r\n                        for (j=0; j<v.length; j++) {\r\n                            cv = v[j];\r\n                            if (y >= cv[0][1] && y <= cv[3][1] && x >= lex[0] && x <= rex[0]) {\r\n                                return {seriesIndex:s.index, pointIndex:j, gridData:null, data:s.data[j]};\r\n                            }\r\n                        }         \r\n                        break;           \r\n                    \r\n                    case $.jqplot.LineRenderer:\r\n                        x = gridpos.x;\r\n                        y = gridpos.y;\r\n                        r = s.renderer;\r\n                        if (s.show) {\r\n                            if ((s.fill || (s.renderer.bands.show && s.renderer.bands.fill)) && (!plot.plugins.highlighter || !plot.plugins.highlighter.show)) {\r\n                                // first check if it is in bounding box\r\n                                var inside = false;\r\n                                if (x>s._boundingBox[0][0] && x<s._boundingBox[1][0] && y>s._boundingBox[1][1] && y<s._boundingBox[0][1]) { \r\n                                    // now check the crossing number   \r\n                                    \r\n                                    var numPoints = s._areaPoints.length;\r\n                                    var ii;\r\n                                    var j = numPoints-1;\r\n\r\n                                    for(var ii=0; ii < numPoints; ii++) { \r\n                                        var vertex1 = [s._areaPoints[ii][0], s._areaPoints[ii][1]];\r\n                                        var vertex2 = [s._areaPoints[j][0], s._areaPoints[j][1]];\r\n\r\n                                        if (vertex1[1] < y && vertex2[1] >= y || vertex2[1] < y && vertex1[1] >= y)     {\r\n                                            if (vertex1[0] + (y - vertex1[1]) / (vertex2[1] - vertex1[1]) * (vertex2[0] - vertex1[0]) < x) {\r\n                                                inside = !inside;\r\n                                            }\r\n                                        }\r\n\r\n                                        j = ii;\r\n                                    }        \r\n                                }\r\n                                if (inside) {\r\n                                    return {seriesIndex:i, pointIndex:null, gridData:s.gridData, data:s.data, points:s._areaPoints};\r\n                                }\r\n                                break;\r\n                                \r\n                            }\r\n\r\n                            else {\r\n                                t = s.markerRenderer.size/2+s.neighborThreshold;\r\n                                threshold = (t > 0) ? t : 0;\r\n                                for (var j=0; j<s.gridData.length; j++) {\r\n                                    p = s.gridData[j];\r\n                                    // neighbor looks different to OHLC chart.\r\n                                    if (r.constructor == $.jqplot.OHLCRenderer) {\r\n                                        if (r.candleStick) {\r\n                                            var yp = s._yaxis.series_u2p;\r\n                                            if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {\r\n                                                return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                            }\r\n                                        }\r\n                                        // if an open hi low close chart\r\n                                        else if (!r.hlc){\r\n                                            var yp = s._yaxis.series_u2p;\r\n                                            if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {\r\n                                                return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                            }\r\n                                        }\r\n                                        // a hi low close chart\r\n                                        else {\r\n                                            var yp = s._yaxis.series_u2p;\r\n                                            if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) {\r\n                                                return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                            }\r\n                                        }\r\n                            \r\n                                    }\r\n                                    else if (p[0] != null && p[1] != null){\r\n                                        d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) );\r\n                                        if (d <= threshold && (d <= d0 || d0 == null)) {\r\n                                           d0 = d;\r\n                                           return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                        }\r\n                                    }\r\n                                } \r\n                            }\r\n                        }\r\n                        break;\r\n                        \r\n                    default:\r\n                        x = gridpos.x;\r\n                        y = gridpos.y;\r\n                        r = s.renderer;\r\n                        if (s.show) {\r\n                            t = s.markerRenderer.size/2+s.neighborThreshold;\r\n                            threshold = (t > 0) ? t : 0;\r\n                            for (var j=0; j<s.gridData.length; j++) {\r\n                                p = s.gridData[j];\r\n                                // neighbor looks different to OHLC chart.\r\n                                if (r.constructor == $.jqplot.OHLCRenderer) {\r\n                                    if (r.candleStick) {\r\n                                        var yp = s._yaxis.series_u2p;\r\n                                        if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {\r\n                                            return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                        }\r\n                                    }\r\n                                    // if an open hi low close chart\r\n                                    else if (!r.hlc){\r\n                                        var yp = s._yaxis.series_u2p;\r\n                                        if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) {\r\n                                            return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                        }\r\n                                    }\r\n                                    // a hi low close chart\r\n                                    else {\r\n                                        var yp = s._yaxis.series_u2p;\r\n                                        if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) {\r\n                                            return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                        }\r\n                                    }\r\n                            \r\n                                }\r\n                                else {\r\n                                    d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) );\r\n                                    if (d <= threshold && (d <= d0 || d0 == null)) {\r\n                                       d0 = d;\r\n                                       return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]};\r\n                                    }\r\n                                }\r\n                            } \r\n                        }\r\n                        break;\r\n                }\r\n            }\r\n            \r\n            return null;\r\n        }\r\n        \r\n        \r\n        \r\n        this.onClick = function(ev) {\r\n            // Event passed in is normalized and will have data attribute.\r\n            // Event passed out is unnormalized.\r\n            var positions = getEventPosition(ev);\r\n            var p = ev.data.plot;\r\n            var neighbor = checkIntersection(positions.gridPos, p);\r\n            var evt = $.Event('jqplotClick');\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]);\r\n        };\r\n        \r\n        this.onDblClick = function(ev) {\r\n            // Event passed in is normalized and will have data attribute.\r\n            // Event passed out is unnormalized.\r\n            var positions = getEventPosition(ev);\r\n            var p = ev.data.plot;\r\n            var neighbor = checkIntersection(positions.gridPos, p);\r\n            var evt = $.Event('jqplotDblClick');\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]);\r\n        };\r\n        \r\n        this.onMouseDown = function(ev) {\r\n            var positions = getEventPosition(ev);\r\n            var p = ev.data.plot;\r\n            var neighbor = checkIntersection(positions.gridPos, p);\r\n            var evt = $.Event('jqplotMouseDown');\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]);\r\n        };\r\n        \r\n        this.onMouseUp = function(ev) {\r\n            var positions = getEventPosition(ev);\r\n            var evt = $.Event('jqplotMouseUp');\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, ev.data.plot]);\r\n        };\r\n        \r\n        this.onRightClick = function(ev) {\r\n            var positions = getEventPosition(ev);\r\n            var p = ev.data.plot;\r\n            var neighbor = checkIntersection(positions.gridPos, p);\r\n            if (p.captureRightClick) {\r\n                if (ev.which == 3) {\r\n                var evt = $.Event('jqplotRightClick');\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                    $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]);\r\n                }\r\n                else {\r\n                var evt = $.Event('jqplotMouseUp');\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                    $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]);\r\n                }\r\n            }\r\n        };\r\n        \r\n        this.onMouseMove = function(ev) {\r\n            var positions = getEventPosition(ev);\r\n            var p = ev.data.plot;\r\n            var neighbor = checkIntersection(positions.gridPos, p);\r\n            var evt = $.Event('jqplotMouseMove');\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]);\r\n        };\r\n        \r\n        this.onMouseEnter = function(ev) {\r\n            var positions = getEventPosition(ev);\r\n            var p = ev.data.plot;\r\n            var evt = $.Event('jqplotMouseEnter');\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            evt.relatedTarget = ev.relatedTarget;\r\n            $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, p]);\r\n        };\r\n        \r\n        this.onMouseLeave = function(ev) {\r\n            var positions = getEventPosition(ev);\r\n            var p = ev.data.plot;\r\n            var evt = $.Event('jqplotMouseLeave');\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            evt.relatedTarget = ev.relatedTarget;\r\n            $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, p]);\r\n        };\r\n        \r\n        // method: drawSeries\r\n        // Redraws all or just one series on the plot.  No axis scaling\r\n        // is performed and no other elements on the plot are redrawn.\r\n        // options is an options object to pass on to the series renderers.\r\n        // It can be an empty object {}.  idx is the series index\r\n        // to redraw if only one series is to be redrawn.\r\n        this.drawSeries = function(options, idx){\r\n            var i, series, ctx;\r\n            // if only one argument passed in and it is a number, use it ad idx.\r\n            idx = (typeof(options) === \"number\" && idx == null) ? options : idx;\r\n            options = (typeof(options) === \"object\") ? options : {};\r\n            // draw specified series\r\n            if (idx != undefined) {\r\n                series = this.series[idx];\r\n                ctx = series.shadowCanvas._ctx;\r\n                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n                series.drawShadow(ctx, options, this);\r\n                ctx = series.canvas._ctx;\r\n                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n                series.draw(ctx, options, this);\r\n                if (series.renderer.constructor == $.jqplot.BezierCurveRenderer) {\r\n                    if (idx < this.series.length - 1) {\r\n                        this.drawSeries(idx+1); \r\n                    }\r\n                }\r\n            }\r\n            \r\n            else {\r\n                // if call series drawShadow method first, in case all series shadows\r\n                // should be drawn before any series.  This will ensure, like for \r\n                // stacked bar plots, that shadows don't overlap series.\r\n                for (i=0; i<this.series.length; i++) {\r\n                    // first clear the canvas\r\n                    series = this.series[i];\r\n                    ctx = series.shadowCanvas._ctx;\r\n                    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n                    series.drawShadow(ctx, options, this);\r\n                    ctx = series.canvas._ctx;\r\n                    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n                    series.draw(ctx, options, this);\r\n                }\r\n            }\r\n            options = idx = i = series = ctx = null;\r\n        };\r\n        \r\n        // method: moveSeriesToFront\r\n        // This method requires jQuery 1.4+\r\n        // Moves the specified series canvas in front of all other series canvases.\r\n        // This effectively \"draws\" the specified series on top of all other series,\r\n        // although it is performed through DOM manipulation, no redrawing is performed.\r\n        //\r\n        // Parameters:\r\n        // idx - 0 based index of the series to move.  This will be the index of the series\r\n        // as it was first passed into the jqplot function.\r\n        this.moveSeriesToFront = function (idx) { \r\n            idx = parseInt(idx, 10);\r\n            var stackIndex = $.inArray(idx, this.seriesStack);\r\n            // if already in front, return\r\n            if (stackIndex == -1) {\r\n                return;\r\n            }\r\n            if (stackIndex == this.seriesStack.length -1) {\r\n                this.previousSeriesStack = this.seriesStack.slice(0);\r\n                return;\r\n            }\r\n            var opidx = this.seriesStack[this.seriesStack.length -1];\r\n            var serelem = this.series[idx].canvas._elem.detach();\r\n            var shadelem = this.series[idx].shadowCanvas._elem.detach();\r\n            this.series[opidx].shadowCanvas._elem.after(shadelem);\r\n            this.series[opidx].canvas._elem.after(serelem);\r\n            this.previousSeriesStack = this.seriesStack.slice(0);\r\n            this.seriesStack.splice(stackIndex, 1);\r\n            this.seriesStack.push(idx);\r\n        };\r\n        \r\n        // method: moveSeriesToBack\r\n        // This method requires jQuery 1.4+\r\n        // Moves the specified series canvas behind all other series canvases.\r\n        //\r\n        // Parameters:\r\n        // idx - 0 based index of the series to move.  This will be the index of the series\r\n        // as it was first passed into the jqplot function.\r\n        this.moveSeriesToBack = function (idx) {\r\n            idx = parseInt(idx, 10);\r\n            var stackIndex = $.inArray(idx, this.seriesStack);\r\n            // if already in back, return\r\n            if (stackIndex == 0 || stackIndex == -1) {\r\n                return;\r\n            }\r\n            var opidx = this.seriesStack[0];\r\n            var serelem = this.series[idx].canvas._elem.detach();\r\n            var shadelem = this.series[idx].shadowCanvas._elem.detach();\r\n            this.series[opidx].shadowCanvas._elem.before(shadelem);\r\n            this.series[opidx].canvas._elem.before(serelem);\r\n            this.previousSeriesStack = this.seriesStack.slice(0);\r\n            this.seriesStack.splice(stackIndex, 1);\r\n            this.seriesStack.unshift(idx);\r\n        };\r\n        \r\n        // method: restorePreviousSeriesOrder\r\n        // This method requires jQuery 1.4+\r\n        // Restore the series canvas order to its previous state.\r\n        // Useful to put a series back where it belongs after moving\r\n        // it to the front.\r\n        this.restorePreviousSeriesOrder = function () {\r\n            var i, j, serelem, shadelem, temp, move, keep;\r\n            // if no change, return.\r\n            if (this.seriesStack == this.previousSeriesStack) {\r\n                return;\r\n            }\r\n            for (i=1; i<this.previousSeriesStack.length; i++) {\r\n                move = this.previousSeriesStack[i];\r\n                keep = this.previousSeriesStack[i-1];\r\n                serelem = this.series[move].canvas._elem.detach();\r\n                shadelem = this.series[move].shadowCanvas._elem.detach();\r\n                this.series[keep].shadowCanvas._elem.after(shadelem);\r\n                this.series[keep].canvas._elem.after(serelem);\r\n            }\r\n            temp = this.seriesStack.slice(0);\r\n            this.seriesStack = this.previousSeriesStack.slice(0);\r\n            this.previousSeriesStack = temp;\r\n        };\r\n        \r\n        // method: restoreOriginalSeriesOrder\r\n        // This method requires jQuery 1.4+\r\n        // Restore the series canvas order to its original order\r\n        // when the plot was created.\r\n        this.restoreOriginalSeriesOrder = function () {\r\n            var i, j, arr=[], serelem, shadelem;\r\n            for (i=0; i<this.series.length; i++) {\r\n                arr.push(i);\r\n            }\r\n            if (this.seriesStack == arr) {\r\n                return;\r\n            }\r\n            this.previousSeriesStack = this.seriesStack.slice(0);\r\n            this.seriesStack = arr;\r\n            for (i=1; i<this.seriesStack.length; i++) {\r\n                serelem = this.series[i].canvas._elem.detach();\r\n                shadelem = this.series[i].shadowCanvas._elem.detach();\r\n                this.series[i-1].shadowCanvas._elem.after(shadelem);\r\n                this.series[i-1].canvas._elem.after(serelem);\r\n            }\r\n        };\r\n        \r\n        this.activateTheme = function (name) {\r\n            this.themeEngine.activate(this, name);\r\n        };\r\n    }\r\n    \r\n    \r\n    // conpute a highlight color or array of highlight colors from given colors.\r\n    $.jqplot.computeHighlightColors  = function(colors) {\r\n        var ret;\r\n        if ($.isArray(colors)) {\r\n            ret = [];\r\n            for (var i=0; i<colors.length; i++){\r\n                var rgba = $.jqplot.getColorComponents(colors[i]);\r\n                var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n                var sum = newrgb[0] + newrgb[1] + newrgb[2];\r\n                for (var j=0; j<3; j++) {\r\n                    // when darkening, lowest color component can be is 60.\r\n                    newrgb[j] = (sum > 660) ?  newrgb[j] * 0.85 : 0.73 * newrgb[j] + 90;\r\n                    newrgb[j] = parseInt(newrgb[j], 10);\r\n                    (newrgb[j] > 255) ? 255 : newrgb[j];\r\n                }\r\n                // newrgb[3] = (rgba[3] > 0.4) ? rgba[3] * 0.4 : rgba[3] * 1.5;\r\n                // newrgb[3] = (rgba[3] > 0.5) ? 0.8 * rgba[3] - .1 : rgba[3] + 0.2;\r\n                newrgb[3] = 0.3 + 0.35 * rgba[3];\r\n                ret.push('rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+newrgb[3]+')');\r\n            }\r\n        }\r\n        else {\r\n            var rgba = $.jqplot.getColorComponents(colors);\r\n            var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n            var sum = newrgb[0] + newrgb[1] + newrgb[2];\r\n            for (var j=0; j<3; j++) {\r\n                // when darkening, lowest color component can be is 60.\r\n                // newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);\r\n                // newrgb[j] = parseInt(newrgb[j], 10);\r\n                newrgb[j] = (sum > 660) ?  newrgb[j] * 0.85 : 0.73 * newrgb[j] + 90;\r\n                newrgb[j] = parseInt(newrgb[j], 10);\r\n                (newrgb[j] > 255) ? 255 : newrgb[j];\r\n            }\r\n            // newrgb[3] = (rgba[3] > 0.4) ? rgba[3] * 0.4 : rgba[3] * 1.5;\r\n            // newrgb[3] = (rgba[3] > 0.5) ? 0.8 * rgba[3] - .1 : rgba[3] + 0.2;\r\n            newrgb[3] = 0.3 + 0.35 * rgba[3];\r\n            ret = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+newrgb[3]+')';\r\n        }\r\n        return ret;\r\n    };\r\n        \r\n   $.jqplot.ColorGenerator = function(colors) {\r\n        colors = colors || $.jqplot.config.defaultColors;\r\n        var idx = 0;\r\n        \r\n        this.next = function () { \r\n            if (idx < colors.length) {\r\n                return colors[idx++];\r\n            }\r\n            else {\r\n                idx = 0;\r\n                return colors[idx++];\r\n            }\r\n        };\r\n        \r\n        this.previous = function () { \r\n            if (idx > 0) {\r\n                return colors[idx--];\r\n            }\r\n            else {\r\n                idx = colors.length-1;\r\n                return colors[idx];\r\n            }\r\n        };\r\n        \r\n        // get a color by index without advancing pointer.\r\n        this.get = function(i) {\r\n            var idx = i - colors.length * Math.floor(i/colors.length);\r\n            return colors[idx];\r\n        };\r\n        \r\n        this.setColors = function(c) {\r\n            colors = c;\r\n        };\r\n        \r\n        this.reset = function() {\r\n            idx = 0;\r\n        };\r\n\r\n        this.getIndex = function() {\r\n            return idx;\r\n        };\r\n\r\n        this.setIndex = function(index) {\r\n            idx = index;\r\n        };\r\n    };\r\n\r\n    // convert a hex color string to rgb string.\r\n    // h - 3 or 6 character hex string, with or without leading #\r\n    // a - optional alpha\r\n    $.jqplot.hex2rgb = function(h, a) {\r\n        h = h.replace('#', '');\r\n        if (h.length == 3) {\r\n            h = h.charAt(0)+h.charAt(0)+h.charAt(1)+h.charAt(1)+h.charAt(2)+h.charAt(2);\r\n        }\r\n        var rgb;\r\n        rgb = 'rgba('+parseInt(h.slice(0,2), 16)+', '+parseInt(h.slice(2,4), 16)+', '+parseInt(h.slice(4,6), 16);\r\n        if (a) {\r\n            rgb += ', '+a;\r\n        }\r\n        rgb += ')';\r\n        return rgb;\r\n    };\r\n    \r\n    // convert an rgb color spec to a hex spec.  ignore any alpha specification.\r\n    $.jqplot.rgb2hex = function(s) {\r\n        var pat = /rgba?\\( *([0-9]{1,3}\\.?[0-9]*%?) *, *([0-9]{1,3}\\.?[0-9]*%?) *, *([0-9]{1,3}\\.?[0-9]*%?) *(?:, *[0-9.]*)?\\)/;\r\n        var m = s.match(pat);\r\n        var h = '#';\r\n        for (var i=1; i<4; i++) {\r\n            var temp;\r\n            if (m[i].search(/%/) != -1) {\r\n                temp = parseInt(255*m[i]/100, 10).toString(16);\r\n                if (temp.length == 1) {\r\n                    temp = '0'+temp;\r\n                }\r\n            }\r\n            else {\r\n                temp = parseInt(m[i], 10).toString(16);\r\n                if (temp.length == 1) {\r\n                    temp = '0'+temp;\r\n                }\r\n            }\r\n            h += temp;\r\n        }\r\n        return h;\r\n    };\r\n    \r\n    // given a css color spec, return an rgb css color spec\r\n    $.jqplot.normalize2rgb = function(s, a) {\r\n        if (s.search(/^ *rgba?\\(/) != -1) {\r\n            return s; \r\n        }\r\n        else if (s.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/) != -1) {\r\n            return $.jqplot.hex2rgb(s, a);\r\n        }\r\n        else {\r\n            throw new Error('Invalid color spec');\r\n        }\r\n    };\r\n    \r\n    // extract the r, g, b, a color components out of a css color spec.\r\n    $.jqplot.getColorComponents = function(s) {\r\n        // check to see if a color keyword.\r\n        s = $.jqplot.colorKeywordMap[s] || s;\r\n        var rgb = $.jqplot.normalize2rgb(s);\r\n        var pat = /rgba?\\( *([0-9]{1,3}\\.?[0-9]*%?) *, *([0-9]{1,3}\\.?[0-9]*%?) *, *([0-9]{1,3}\\.?[0-9]*%?) *,? *([0-9.]* *)?\\)/;\r\n        var m = rgb.match(pat);\r\n        var ret = [];\r\n        for (var i=1; i<4; i++) {\r\n            if (m[i].search(/%/) != -1) {\r\n                ret[i-1] = parseInt(255*m[i]/100, 10);\r\n            }\r\n            else {\r\n                ret[i-1] = parseInt(m[i], 10);\r\n            }\r\n        }\r\n        ret[3] = parseFloat(m[4]) ? parseFloat(m[4]) : 1.0;\r\n        return ret;\r\n    };\r\n    \r\n    $.jqplot.colorKeywordMap = {\r\n        aliceblue: 'rgb(240, 248, 255)',\r\n        antiquewhite: 'rgb(250, 235, 215)',\r\n        aqua: 'rgb( 0, 255, 255)',\r\n        aquamarine: 'rgb(127, 255, 212)',\r\n        azure: 'rgb(240, 255, 255)',\r\n        beige: 'rgb(245, 245, 220)',\r\n        bisque: 'rgb(255, 228, 196)',\r\n        black: 'rgb( 0, 0, 0)',\r\n        blanchedalmond: 'rgb(255, 235, 205)',\r\n        blue: 'rgb( 0, 0, 255)',\r\n        blueviolet: 'rgb(138, 43, 226)',\r\n        brown: 'rgb(165, 42, 42)',\r\n        burlywood: 'rgb(222, 184, 135)',\r\n        cadetblue: 'rgb( 95, 158, 160)',\r\n        chartreuse: 'rgb(127, 255, 0)',\r\n        chocolate: 'rgb(210, 105, 30)',\r\n        coral: 'rgb(255, 127, 80)',\r\n        cornflowerblue: 'rgb(100, 149, 237)',\r\n        cornsilk: 'rgb(255, 248, 220)',\r\n        crimson: 'rgb(220, 20, 60)',\r\n        cyan: 'rgb( 0, 255, 255)',\r\n        darkblue: 'rgb( 0, 0, 139)',\r\n        darkcyan: 'rgb( 0, 139, 139)',\r\n        darkgoldenrod: 'rgb(184, 134, 11)',\r\n        darkgray: 'rgb(169, 169, 169)',\r\n        darkgreen: 'rgb( 0, 100, 0)',\r\n        darkgrey: 'rgb(169, 169, 169)',\r\n        darkkhaki: 'rgb(189, 183, 107)',\r\n        darkmagenta: 'rgb(139, 0, 139)',\r\n        darkolivegreen: 'rgb( 85, 107, 47)',\r\n        darkorange: 'rgb(255, 140, 0)',\r\n        darkorchid: 'rgb(153, 50, 204)',\r\n        darkred: 'rgb(139, 0, 0)',\r\n        darksalmon: 'rgb(233, 150, 122)',\r\n        darkseagreen: 'rgb(143, 188, 143)',\r\n        darkslateblue: 'rgb( 72, 61, 139)',\r\n        darkslategray: 'rgb( 47, 79, 79)',\r\n        darkslategrey: 'rgb( 47, 79, 79)',\r\n        darkturquoise: 'rgb( 0, 206, 209)',\r\n        darkviolet: 'rgb(148, 0, 211)',\r\n        deeppink: 'rgb(255, 20, 147)',\r\n        deepskyblue: 'rgb( 0, 191, 255)',\r\n        dimgray: 'rgb(105, 105, 105)',\r\n        dimgrey: 'rgb(105, 105, 105)',\r\n        dodgerblue: 'rgb( 30, 144, 255)',\r\n        firebrick: 'rgb(178, 34, 34)',\r\n        floralwhite: 'rgb(255, 250, 240)',\r\n        forestgreen: 'rgb( 34, 139, 34)',\r\n        fuchsia: 'rgb(255, 0, 255)',\r\n        gainsboro: 'rgb(220, 220, 220)',\r\n        ghostwhite: 'rgb(248, 248, 255)',\r\n        gold: 'rgb(255, 215, 0)',\r\n        goldenrod: 'rgb(218, 165, 32)',\r\n        gray: 'rgb(128, 128, 128)',\r\n        grey: 'rgb(128, 128, 128)',\r\n        green: 'rgb( 0, 128, 0)',\r\n        greenyellow: 'rgb(173, 255, 47)',\r\n        honeydew: 'rgb(240, 255, 240)',\r\n        hotpink: 'rgb(255, 105, 180)',\r\n        indianred: 'rgb(205, 92, 92)',\r\n        indigo: 'rgb( 75, 0, 130)',\r\n        ivory: 'rgb(255, 255, 240)',\r\n        khaki: 'rgb(240, 230, 140)',\r\n        lavender: 'rgb(230, 230, 250)',\r\n        lavenderblush: 'rgb(255, 240, 245)',\r\n        lawngreen: 'rgb(124, 252, 0)',\r\n        lemonchiffon: 'rgb(255, 250, 205)',\r\n        lightblue: 'rgb(173, 216, 230)',\r\n        lightcoral: 'rgb(240, 128, 128)',\r\n        lightcyan: 'rgb(224, 255, 255)',\r\n        lightgoldenrodyellow: 'rgb(250, 250, 210)',\r\n        lightgray: 'rgb(211, 211, 211)',\r\n        lightgreen: 'rgb(144, 238, 144)',\r\n        lightgrey: 'rgb(211, 211, 211)',\r\n        lightpink: 'rgb(255, 182, 193)',\r\n        lightsalmon: 'rgb(255, 160, 122)',\r\n        lightseagreen: 'rgb( 32, 178, 170)',\r\n        lightskyblue: 'rgb(135, 206, 250)',\r\n        lightslategray: 'rgb(119, 136, 153)',\r\n        lightslategrey: 'rgb(119, 136, 153)',\r\n        lightsteelblue: 'rgb(176, 196, 222)',\r\n        lightyellow: 'rgb(255, 255, 224)',\r\n        lime: 'rgb( 0, 255, 0)',\r\n        limegreen: 'rgb( 50, 205, 50)',\r\n        linen: 'rgb(250, 240, 230)',\r\n        magenta: 'rgb(255, 0, 255)',\r\n        maroon: 'rgb(128, 0, 0)',\r\n        mediumaquamarine: 'rgb(102, 205, 170)',\r\n        mediumblue: 'rgb( 0, 0, 205)',\r\n        mediumorchid: 'rgb(186, 85, 211)',\r\n        mediumpurple: 'rgb(147, 112, 219)',\r\n        mediumseagreen: 'rgb( 60, 179, 113)',\r\n        mediumslateblue: 'rgb(123, 104, 238)',\r\n        mediumspringgreen: 'rgb( 0, 250, 154)',\r\n        mediumturquoise: 'rgb( 72, 209, 204)',\r\n        mediumvioletred: 'rgb(199, 21, 133)',\r\n        midnightblue: 'rgb( 25, 25, 112)',\r\n        mintcream: 'rgb(245, 255, 250)',\r\n        mistyrose: 'rgb(255, 228, 225)',\r\n        moccasin: 'rgb(255, 228, 181)',\r\n        navajowhite: 'rgb(255, 222, 173)',\r\n        navy: 'rgb( 0, 0, 128)',\r\n        oldlace: 'rgb(253, 245, 230)',\r\n        olive: 'rgb(128, 128, 0)',\r\n        olivedrab: 'rgb(107, 142, 35)',\r\n        orange: 'rgb(255, 165, 0)',\r\n        orangered: 'rgb(255, 69, 0)',\r\n        orchid: 'rgb(218, 112, 214)',\r\n        palegoldenrod: 'rgb(238, 232, 170)',\r\n        palegreen: 'rgb(152, 251, 152)',\r\n        paleturquoise: 'rgb(175, 238, 238)',\r\n        palevioletred: 'rgb(219, 112, 147)',\r\n        papayawhip: 'rgb(255, 239, 213)',\r\n        peachpuff: 'rgb(255, 218, 185)',\r\n        peru: 'rgb(205, 133, 63)',\r\n        pink: 'rgb(255, 192, 203)',\r\n        plum: 'rgb(221, 160, 221)',\r\n        powderblue: 'rgb(176, 224, 230)',\r\n        purple: 'rgb(128, 0, 128)',\r\n        red: 'rgb(255, 0, 0)',\r\n        rosybrown: 'rgb(188, 143, 143)',\r\n        royalblue: 'rgb( 65, 105, 225)',\r\n        saddlebrown: 'rgb(139, 69, 19)',\r\n        salmon: 'rgb(250, 128, 114)',\r\n        sandybrown: 'rgb(244, 164, 96)',\r\n        seagreen: 'rgb( 46, 139, 87)',\r\n        seashell: 'rgb(255, 245, 238)',\r\n        sienna: 'rgb(160, 82, 45)',\r\n        silver: 'rgb(192, 192, 192)',\r\n        skyblue: 'rgb(135, 206, 235)',\r\n        slateblue: 'rgb(106, 90, 205)',\r\n        slategray: 'rgb(112, 128, 144)',\r\n        slategrey: 'rgb(112, 128, 144)',\r\n        snow: 'rgb(255, 250, 250)',\r\n        springgreen: 'rgb( 0, 255, 127)',\r\n        steelblue: 'rgb( 70, 130, 180)',\r\n        tan: 'rgb(210, 180, 140)',\r\n        teal: 'rgb( 0, 128, 128)',\r\n        thistle: 'rgb(216, 191, 216)',\r\n        tomato: 'rgb(255, 99, 71)',\r\n        turquoise: 'rgb( 64, 224, 208)',\r\n        violet: 'rgb(238, 130, 238)',\r\n        wheat: 'rgb(245, 222, 179)',\r\n        white: 'rgb(255, 255, 255)',\r\n        whitesmoke: 'rgb(245, 245, 245)',\r\n        yellow: 'rgb(255, 255, 0)',\r\n        yellowgreen: 'rgb(154, 205, 50)'\r\n    };\r\n\r\n    \r\n\r\n\r\n    // class: $.jqplot.AxisLabelRenderer\r\n    // Renderer to place labels on the axes.\r\n    $.jqplot.AxisLabelRenderer = function(options) {\r\n        // Group: Properties\r\n        $.jqplot.ElemContainer.call(this);\r\n        // name of the axis associated with this tick\r\n        this.axis;\r\n        // prop: show\r\n        // whether or not to show the tick (mark and label).\r\n        this.show = true;\r\n        // prop: label\r\n        // The text or html for the label.\r\n        this.label = '';\r\n        this.fontFamily = null;\r\n        this.fontSize = null;\r\n        this.textColor = null;\r\n        this._elem;\r\n        // prop: escapeHTML\r\n        // true to escape HTML entities in the label.\r\n        this.escapeHTML = false;\r\n        \r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.AxisLabelRenderer.prototype = new $.jqplot.ElemContainer();\r\n    $.jqplot.AxisLabelRenderer.prototype.constructor = $.jqplot.AxisLabelRenderer;\r\n    \r\n    $.jqplot.AxisLabelRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.AxisLabelRenderer.prototype.draw = function(ctx, plot) {\r\n        // Memory Leaks patch\r\n        if (this._elem) {\r\n            this._elem.emptyForce();\r\n            this._elem = null;\r\n        }\r\n\r\n        this._elem = $('<div style=\"position:absolute;\" class=\"jqplot-'+this.axis+'-label\"></div>');\r\n        \r\n        if (Number(this.label)) {\r\n            this._elem.css('white-space', 'nowrap');\r\n        }\r\n        \r\n        if (!this.escapeHTML) {\r\n            this._elem.html(this.label);\r\n        }\r\n        else {\r\n            this._elem.text(this.label);\r\n        }\r\n        if (this.fontFamily) {\r\n            this._elem.css('font-family', this.fontFamily);\r\n        }\r\n        if (this.fontSize) {\r\n            this._elem.css('font-size', this.fontSize);\r\n        }\r\n        if (this.textColor) {\r\n            this._elem.css('color', this.textColor);\r\n        }\r\n        \r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.AxisLabelRenderer.prototype.pack = function() {\r\n    };\r\n\r\n    // class: $.jqplot.AxisTickRenderer\r\n    // A \"tick\" object showing the value of a tick/gridline on the plot.\r\n    $.jqplot.AxisTickRenderer = function(options) {\r\n        // Group: Properties\r\n        $.jqplot.ElemContainer.call(this);\r\n        // prop: mark\r\n        // tick mark on the axis.  One of 'inside', 'outside', 'cross', '' or null.\r\n        this.mark = 'outside';\r\n        // name of the axis associated with this tick\r\n        this.axis;\r\n        // prop: showMark\r\n        // whether or not to show the mark on the axis.\r\n        this.showMark = true;\r\n        // prop: showGridline\r\n        // whether or not to draw the gridline on the grid at this tick.\r\n        this.showGridline = true;\r\n        // prop: isMinorTick\r\n        // if this is a minor tick.\r\n        this.isMinorTick = false;\r\n        // prop: size\r\n        // Length of the tick beyond the grid in pixels.\r\n        // DEPRECATED: This has been superceeded by markSize\r\n        this.size = 4;\r\n        // prop:  markSize\r\n        // Length of the tick marks in pixels.  For 'cross' style, length\r\n        // will be stoked above and below axis, so total length will be twice this.\r\n        this.markSize = 6;\r\n        // prop: show\r\n        // whether or not to show the tick (mark and label).\r\n        // Setting this to false requires more testing.  It is recommended\r\n        // to set showLabel and showMark to false instead.\r\n        this.show = true;\r\n        // prop: showLabel\r\n        // whether or not to show the label.\r\n        this.showLabel = true;\r\n        this.label = null;\r\n        this.value = null;\r\n        this._styles = {};\r\n        // prop: formatter\r\n        // A class of a formatter for the tick text.  sprintf by default.\r\n        this.formatter = $.jqplot.DefaultTickFormatter;\r\n        // prop: prefix\r\n        // String to prepend to the tick label.\r\n        // Prefix is prepended to the formatted tick label.\r\n        this.prefix = '';\r\n        // prop: suffix\r\n        // String to append to the tick label.\r\n        // Suffix is appended to the formatted tick label.\r\n        this.suffix = '';\r\n        // prop: formatString\r\n        // string passed to the formatter.\r\n        this.formatString = '';\r\n        // prop: fontFamily\r\n        // css spec for the font-family css attribute.\r\n        this.fontFamily;\r\n        // prop: fontSize\r\n        // css spec for the font-size css attribute.\r\n        this.fontSize;\r\n        // prop: textColor\r\n        // css spec for the color attribute.\r\n        this.textColor;\r\n        // prop: escapeHTML\r\n        // true to escape HTML entities in the label.\r\n        this.escapeHTML = false;\r\n        this._elem;\r\n        this._breakTick = false;\r\n        \r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.AxisTickRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.AxisTickRenderer.prototype = new $.jqplot.ElemContainer();\r\n    $.jqplot.AxisTickRenderer.prototype.constructor = $.jqplot.AxisTickRenderer;\r\n    \r\n    $.jqplot.AxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) {\r\n        this.value = value;\r\n        this.axis = axisName;\r\n        if (isMinor) {\r\n            this.isMinorTick = true;\r\n        }\r\n        return this;\r\n    };\r\n    \r\n    $.jqplot.AxisTickRenderer.prototype.draw = function() {\r\n        if (this.label === null) {\r\n            this.label = this.prefix + this.formatter(this.formatString, this.value) + this.suffix;\r\n        }\r\n        var style = {position: 'absolute'};\r\n        if (Number(this.label)) {\r\n            style['whitSpace'] = 'nowrap';\r\n        }\r\n        \r\n        // Memory Leaks patch\r\n        if (this._elem) {\r\n            this._elem.emptyForce();\r\n            this._elem = null;\r\n        }\r\n\r\n        this._elem = $(document.createElement('div'));\r\n        this._elem.addClass(\"jqplot-\"+this.axis+\"-tick\");\r\n        \r\n        if (!this.escapeHTML) {\r\n            this._elem.html(this.label);\r\n        }\r\n        else {\r\n            this._elem.text(this.label);\r\n        }\r\n        \r\n        this._elem.css(style);\r\n\r\n        for (var s in this._styles) {\r\n            this._elem.css(s, this._styles[s]);\r\n        }\r\n        if (this.fontFamily) {\r\n            this._elem.css('font-family', this.fontFamily);\r\n        }\r\n        if (this.fontSize) {\r\n            this._elem.css('font-size', this.fontSize);\r\n        }\r\n        if (this.textColor) {\r\n            this._elem.css('color', this.textColor);\r\n        }\r\n        if (this._breakTick) {\r\n          this._elem.addClass('jqplot-breakTick');\r\n        }\r\n        \r\n        return this._elem;\r\n    };\r\n        \r\n    $.jqplot.DefaultTickFormatter = function (format, val) {\r\n        if (typeof val == 'number') {\r\n            if (!format) {\r\n                format = $.jqplot.config.defaultTickFormatString;\r\n            }\r\n            return $.jqplot.sprintf(format, val);\r\n        }\r\n        else {\r\n            return String(val);\r\n        }\r\n    };\r\n        \r\n    $.jqplot.PercentTickFormatter = function (format, val) {\r\n        if (typeof val == 'number') {\r\n            val = 100 * val;\r\n            if (!format) {\r\n                format = $.jqplot.config.defaultTickFormatString;\r\n            }\r\n            return $.jqplot.sprintf(format, val);\r\n        }\r\n        else {\r\n            return String(val);\r\n        }\r\n    };\r\n    \r\n    $.jqplot.AxisTickRenderer.prototype.pack = function() {\r\n    };\r\n     \r\n    // Class: $.jqplot.CanvasGridRenderer\r\n    // The default jqPlot grid renderer, creating a grid on a canvas element.\r\n    // The renderer has no additional options beyond the <Grid> class.\r\n    $.jqplot.CanvasGridRenderer = function(){\r\n        this.shadowRenderer = new $.jqplot.ShadowRenderer();\r\n    };\r\n    \r\n    // called with context of Grid object\r\n    $.jqplot.CanvasGridRenderer.prototype.init = function(options) {\r\n        this._ctx;\r\n        $.extend(true, this, options);\r\n        // set the shadow renderer options\r\n        var sopts = {lineJoin:'miter', lineCap:'round', fill:false, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.shadowWidth, closePath:false, strokeStyle:this.shadowColor};\r\n        this.renderer.shadowRenderer.init(sopts);\r\n    };\r\n    \r\n    // called with context of Grid.\r\n    $.jqplot.CanvasGridRenderer.prototype.createElement = function(plot) {\r\n        var elem;\r\n        // Memory Leaks patch\r\n        if (this._elem) {\r\n          if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {\r\n            elem = this._elem.get(0);\r\n            window.G_vmlCanvasManager.uninitElement(elem);\r\n            elem = null;\r\n          }\r\n          \r\n          this._elem.emptyForce();\r\n          this._elem = null;\r\n        }\r\n      \r\n        elem = plot.canvasManager.getCanvas();\r\n\r\n        var w = this._plotDimensions.width;\r\n        var h = this._plotDimensions.height;\r\n        elem.width = w;\r\n        elem.height = h;\r\n        this._elem = $(elem);\r\n        this._elem.addClass('jqplot-grid-canvas');\r\n        this._elem.css({ position: 'absolute', left: 0, top: 0 });\r\n        \r\n        elem = plot.canvasManager.initCanvas(elem);\r\n\r\n        this._top = this._offsets.top;\r\n        this._bottom = h - this._offsets.bottom;\r\n        this._left = this._offsets.left;\r\n        this._right = w - this._offsets.right;\r\n        this._width = this._right - this._left;\r\n        this._height = this._bottom - this._top;\r\n        // avoid memory leak\r\n        elem = null;\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.CanvasGridRenderer.prototype.draw = function() {\r\n        this._ctx = this._elem.get(0).getContext(\"2d\");\r\n        var ctx = this._ctx;\r\n        var axes = this._axes;\r\n        // Add the grid onto the grid canvas.  This is the bottom most layer.\r\n        ctx.save();\r\n        ctx.clearRect(0, 0, this._plotDimensions.width, this._plotDimensions.height);\r\n        ctx.fillStyle = this.backgroundColor || this.background;\r\n        ctx.fillRect(this._left, this._top, this._width, this._height);\r\n        \r\n        ctx.save();\r\n        ctx.lineJoin = 'miter';\r\n        ctx.lineCap = 'butt';\r\n        ctx.lineWidth = this.gridLineWidth;\r\n        ctx.strokeStyle = this.gridLineColor;\r\n        var b, e, s, m;\r\n        var ax = ['xaxis', 'yaxis', 'x2axis', 'y2axis'];\r\n        for (var i=4; i>0; i--) {\r\n            var name = ax[i-1];\r\n            var axis = axes[name];\r\n            var ticks = axis._ticks;\r\n            var numticks = ticks.length;\r\n            if (axis.show) {\r\n                if (axis.drawBaseline) {\r\n                    var bopts = {};\r\n                    if (axis.baselineWidth !== null) {\r\n                        bopts.lineWidth = axis.baselineWidth;\r\n                    }\r\n                    if (axis.baselineColor !== null) {\r\n                        bopts.strokeStyle = axis.baselineColor;\r\n                    }\r\n                    switch (name) {\r\n                        case 'xaxis':\r\n                            drawLine (this._left, this._bottom, this._right, this._bottom, bopts);\r\n                            break;\r\n                        case 'yaxis':\r\n                            drawLine (this._left, this._bottom, this._left, this._top, bopts);\r\n                            break;\r\n                        case 'x2axis':\r\n                            drawLine (this._left, this._bottom, this._right, this._bottom, bopts);\r\n                            break;\r\n                        case 'y2axis':\r\n                            drawLine (this._right, this._bottom, this._right, this._top, bopts);\r\n                            break;\r\n                    }\r\n                }\r\n                for (var j=numticks; j>0; j--) {\r\n                    var t = ticks[j-1];\r\n                    if (t.show) {\r\n                        var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                        switch (name) {\r\n                            case 'xaxis':\r\n                                // draw the grid line if we should\r\n                                if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) {\r\n                                    drawLine(pos, this._top, pos, this._bottom);\r\n                                }\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._bottom;\r\n                                            e = this._bottom+s;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._bottom-s;\r\n                                            e = this._bottom;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._bottom-s;\r\n                                            e = this._bottom+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._bottom;\r\n                                            e = this._bottom+s;\r\n                                            break;\r\n                                    }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false});\r\n                                    }\r\n                                    // draw the line\r\n                                    drawLine(pos, b, pos, e);\r\n                                }\r\n                                break;\r\n                            case 'yaxis':\r\n                                // draw the grid line\r\n                                if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) {\r\n                                    drawLine(this._right, pos, this._left, pos);\r\n                                }\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._left-s;\r\n                                            e = this._left;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._left;\r\n                                            e = this._left+s;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._left-s;\r\n                                            e = this._left+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._left-s;\r\n                                            e = this._left;\r\n                                            break;\r\n                                            }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor});\r\n                                }\r\n                                break;\r\n                            case 'x2axis':\r\n                                // draw the grid line\r\n                                if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) {\r\n                                    drawLine(pos, this._bottom, pos, this._top);\r\n                                }\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._top-s;\r\n                                            e = this._top;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._top;\r\n                                            e = this._top+s;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._top-s;\r\n                                            e = this._top+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._top-s;\r\n                                            e = this._top;\r\n                                            break;\r\n                                            }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(pos, b, pos, e);\r\n                                }\r\n                                break;\r\n                            case 'y2axis':\r\n                                // draw the grid line\r\n                                if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) {\r\n                                    drawLine(this._left, pos, this._right, pos);\r\n                                }\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._right;\r\n                                            e = this._right+s;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._right-s;\r\n                                            e = this._right;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._right-s;\r\n                                            e = this._right+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._right;\r\n                                            e = this._right+s;\r\n                                            break;\r\n                                            }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor});\r\n                                }\r\n                                break;\r\n                            default:\r\n                                break;\r\n                        }\r\n                    }\r\n                }\r\n                t = null;\r\n            }\r\n            axis = null;\r\n            ticks = null;\r\n        }\r\n        // Now draw grid lines for additional y axes\r\n        //////\r\n        // TO DO: handle yMidAxis\r\n        //////\r\n        ax = ['y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis'];\r\n        for (var i=7; i>0; i--) {\r\n            var axis = axes[ax[i-1]];\r\n            var ticks = axis._ticks;\r\n            if (axis.show) {\r\n                var tn = ticks[axis.numberTicks-1];\r\n                var t0 = ticks[0];\r\n                var left = axis.getLeft();\r\n                var points = [[left, tn.getTop() + tn.getHeight()/2], [left, t0.getTop() + t0.getHeight()/2 + 1.0]];\r\n                // draw the shadow\r\n                if (this.shadow) {\r\n                    this.renderer.shadowRenderer.draw(ctx, points, {lineCap:'butt', fill:false, closePath:false});\r\n                }\r\n                // draw the line\r\n                drawLine(points[0][0], points[0][1], points[1][0], points[1][1], {lineCap:'butt', strokeStyle:axis.borderColor, lineWidth:axis.borderWidth});\r\n                // draw the tick marks\r\n                for (var j=ticks.length; j>0; j--) {\r\n                    var t = ticks[j-1];\r\n                    s = t.markSize;\r\n                    m = t.mark;\r\n                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                    if (t.showMark && t.mark) {\r\n                        switch (m) {\r\n                            case 'outside':\r\n                                b = left;\r\n                                e = left+s;\r\n                                break;\r\n                            case 'inside':\r\n                                b = left-s;\r\n                                e = left;\r\n                                break;\r\n                            case 'cross':\r\n                                b = left-s;\r\n                                e = left+s;\r\n                                break;\r\n                            default:\r\n                                b = left;\r\n                                e = left+s;\r\n                                break;\r\n                        }\r\n                        points = [[b,pos], [e,pos]];\r\n                        // draw the shadow\r\n                        if (this.shadow) {\r\n                            this.renderer.shadowRenderer.draw(ctx, points, {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false});\r\n                        }\r\n                        // draw the line\r\n                        drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor});\r\n                    }\r\n                    t = null;\r\n                }\r\n                t0 = null;\r\n            }\r\n            axis = null;\r\n            ticks =  null;\r\n        }\r\n        \r\n        ctx.restore();\r\n        \r\n        function drawLine(bx, by, ex, ey, opts) {\r\n            ctx.save();\r\n            opts = opts || {};\r\n            if (opts.lineWidth == null || opts.lineWidth != 0){\r\n                $.extend(true, ctx, opts);\r\n                ctx.beginPath();\r\n                ctx.moveTo(bx, by);\r\n                ctx.lineTo(ex, ey);\r\n                ctx.stroke();\r\n                ctx.restore();\r\n            }\r\n        }\r\n        \r\n        if (this.shadow) {\r\n            var points = [[this._left, this._bottom], [this._right, this._bottom], [this._right, this._top]];\r\n            this.renderer.shadowRenderer.draw(ctx, points);\r\n        }\r\n        // Now draw border around grid.  Use axis border definitions. start at\r\n        // upper left and go clockwise.\r\n        if (this.borderWidth != 0 && this.drawBorder) {\r\n            drawLine (this._left, this._top, this._right, this._top, {lineCap:'round', strokeStyle:axes.x2axis.borderColor, lineWidth:axes.x2axis.borderWidth});\r\n            drawLine (this._right, this._top, this._right, this._bottom, {lineCap:'round', strokeStyle:axes.y2axis.borderColor, lineWidth:axes.y2axis.borderWidth});\r\n            drawLine (this._right, this._bottom, this._left, this._bottom, {lineCap:'round', strokeStyle:axes.xaxis.borderColor, lineWidth:axes.xaxis.borderWidth});\r\n            drawLine (this._left, this._bottom, this._left, this._top, {lineCap:'round', strokeStyle:axes.yaxis.borderColor, lineWidth:axes.yaxis.borderWidth});\r\n        }\r\n        // ctx.lineWidth = this.borderWidth;\r\n        // ctx.strokeStyle = this.borderColor;\r\n        // ctx.strokeRect(this._left, this._top, this._width, this._height);\r\n        \r\n        ctx.restore();\r\n        ctx =  null;\r\n        axes = null;\r\n    };\r\n \r\n    // Class: $.jqplot.DivTitleRenderer\r\n    // The default title renderer for jqPlot.  This class has no options beyond the <Title> class. \r\n    $.jqplot.DivTitleRenderer = function() {\r\n    };\r\n    \r\n    $.jqplot.DivTitleRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.DivTitleRenderer.prototype.draw = function() {\r\n        // Memory Leaks patch\r\n        if (this._elem) {\r\n            this._elem.emptyForce();\r\n            this._elem = null;\r\n        }\r\n\r\n        var r = this.renderer;\r\n        var elem = document.createElement('div');\r\n        this._elem = $(elem);\r\n        this._elem.addClass('jqplot-title');\r\n\r\n        if (!this.text) {\r\n            this.show = false;\r\n            this._elem.height(0);\r\n            this._elem.width(0);\r\n        }\r\n        else if (this.text) {\r\n            var color;\r\n            if (this.color) {\r\n                color = this.color;\r\n            }\r\n            else if (this.textColor) {\r\n                color = this.textColor;\r\n            }\r\n\r\n            // don't trust that a stylesheet is present, set the position.\r\n            var styles = {position:'absolute', top:'0px', left:'0px'};\r\n\r\n            if (this._plotWidth) {\r\n                styles['width'] = this._plotWidth+'px';\r\n            }\r\n            if (this.fontSize) {\r\n                styles['fontSize'] = this.fontSize;\r\n            }\r\n            if (typeof this.textAlign === 'string') {\r\n                styles['textAlign'] = this.textAlign;\r\n            }\r\n            else {\r\n                styles['textAlign'] = 'center';\r\n            }\r\n            if (color) {\r\n                styles['color'] = color;\r\n            }\r\n            if (this.paddingBottom) {\r\n                styles['paddingBottom'] = this.paddingBottom;\r\n            }\r\n            if (this.fontFamily) {\r\n                styles['fontFamily'] = this.fontFamily;\r\n            }\r\n\r\n            this._elem.css(styles);\r\n            if (this.escapeHtml) {\r\n                this._elem.text(this.text);\r\n            }\r\n            else {\r\n                this._elem.html(this.text);\r\n            }\r\n\r\n\r\n            // styletext += (this._plotWidth) ? 'width:'+this._plotWidth+'px;' : '';\r\n            // styletext += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';\r\n            // styletext += (this.textAlign) ? 'text-align:'+this.textAlign+';' : 'text-align:center;';\r\n            // styletext += (color) ? 'color:'+color+';' : '';\r\n            // styletext += (this.paddingBottom) ? 'padding-bottom:'+this.paddingBottom+';' : '';\r\n            // this._elem = $('<div class=\"jqplot-title\" style=\"'+styletext+'\">'+this.text+'</div>');\r\n            // if (this.fontFamily) {\r\n            //     this._elem.css('font-family', this.fontFamily);\r\n            // }\r\n        }\r\n\r\n        elem = null;\r\n        \r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.DivTitleRenderer.prototype.pack = function() {\r\n        // nothing to do here\r\n    };\r\n  \r\n\r\n    var dotlen = 0.1;\r\n\r\n    $.jqplot.LinePattern = function (ctx, pattern) {\r\n\r\n        var defaultLinePatterns = {\r\n            dotted: [ dotlen, $.jqplot.config.dotGapLength ],\r\n            dashed: [ $.jqplot.config.dashLength, $.jqplot.config.gapLength ],\r\n            solid: null\r\n        };\r\n\r\n        if (typeof pattern === 'string') {\r\n            if (pattern[0] === '.' || pattern[0] === '-') {\r\n                var s = pattern;\r\n                pattern = [];\r\n                for (var i=0, imax=s.length; i<imax; i++) {\r\n                    if (s[i] === '.') {\r\n                        pattern.push( dotlen );\r\n                    }\r\n                    else if (s[i] === '-') {\r\n                        pattern.push( $.jqplot.config.dashLength );\r\n                    }\r\n                    else {\r\n                        continue;\r\n                    }\r\n                    pattern.push( $.jqplot.config.gapLength );\r\n                }\r\n            }\r\n            else {\r\n                pattern = defaultLinePatterns[pattern];\r\n            }\r\n        }\r\n\r\n        if (!(pattern && pattern.length)) {\r\n            return ctx;\r\n        }\r\n\r\n        var patternIndex = 0;\r\n        var patternDistance = pattern[0];\r\n        var px = 0;\r\n        var py = 0;\r\n        var pathx0 = 0;\r\n        var pathy0 = 0;\r\n\r\n        var moveTo = function (x, y) {\r\n            ctx.moveTo( x, y );\r\n            px = x;\r\n            py = y;\r\n            pathx0 = x;\r\n            pathy0 = y;\r\n        };\r\n\r\n        var lineTo = function (x, y) {\r\n            var scale = ctx.lineWidth;\r\n            var dx = x - px;\r\n            var dy = y - py;\r\n            var dist = Math.sqrt(dx*dx+dy*dy);\r\n            if ((dist > 0) && (scale > 0)) {\r\n                dx /= dist;\r\n                dy /= dist;\r\n                while (true) {\r\n                    var dp = scale * patternDistance;\r\n                    if (dp < dist) {\r\n                        px += dp * dx;\r\n                        py += dp * dy;\r\n                        if ((patternIndex & 1) == 0) {\r\n                            ctx.lineTo( px, py );\r\n                        }\r\n                        else {\r\n                            ctx.moveTo( px, py );\r\n                        }\r\n                        dist -= dp;\r\n                        patternIndex++;\r\n                        if (patternIndex >= pattern.length) {\r\n                            patternIndex = 0;\r\n                        }\r\n                        patternDistance = pattern[patternIndex];\r\n                    }\r\n                    else {\r\n                        px = x;\r\n                        py = y;\r\n                        if ((patternIndex & 1) == 0) {\r\n                            ctx.lineTo( px, py );\r\n                        }\r\n                        else {\r\n                            ctx.moveTo( px, py );\r\n                        }\r\n                        patternDistance -= dist / scale;\r\n                        break;\r\n                    }\r\n                }\r\n            }\r\n        };\r\n\r\n        var beginPath = function () {\r\n            ctx.beginPath();\r\n        };\r\n\r\n        var closePath = function () {\r\n            lineTo( pathx0, pathy0 );\r\n        };\r\n\r\n        return {\r\n            moveTo: moveTo,\r\n            lineTo: lineTo,\r\n            beginPath: beginPath,\r\n            closePath: closePath\r\n        };\r\n    };\r\n\r\n    // Class: $.jqplot.LineRenderer\r\n    // The default line renderer for jqPlot, this class has no options beyond the <Series> class.\r\n    // Draws series as a line.\r\n    $.jqplot.LineRenderer = function(){\r\n        this.shapeRenderer = new $.jqplot.ShapeRenderer();\r\n        this.shadowRenderer = new $.jqplot.ShadowRenderer();\r\n    };\r\n    \r\n    // called with scope of series.\r\n    $.jqplot.LineRenderer.prototype.init = function(options, plot) {\r\n        // Group: Properties\r\n        //\r\n        options = options || {};\r\n        this._type='line';\r\n        this.renderer.animation = {\r\n            show: false,\r\n            direction: 'left',\r\n            speed: 2500,\r\n            _supported: true\r\n        };\r\n        // prop: smooth\r\n        // True to draw a smoothed (interpolated) line through the data points\r\n        // with automatically computed number of smoothing points.\r\n        // Set to an integer number > 2 to specify number of smoothing points\r\n        // to use between each data point.\r\n        this.renderer.smooth = false;  // true or a number > 2 for smoothing.\r\n        this.renderer.tension = null; // null to auto compute or a number typically > 6.  Fewer points requires higher tension.\r\n        // prop: constrainSmoothing\r\n        // True to use a more accurate smoothing algorithm that will\r\n        // not overshoot any data points.  False to allow overshoot but\r\n        // produce a smoother looking line.\r\n        this.renderer.constrainSmoothing = true;\r\n        // this is smoothed data in grid coordinates, like gridData\r\n        this.renderer._smoothedData = [];\r\n        // this is smoothed data in plot units (plot coordinates), like plotData.\r\n        this.renderer._smoothedPlotData = [];\r\n        this.renderer._hiBandGridData = [];\r\n        this.renderer._lowBandGridData = [];\r\n        this.renderer._hiBandSmoothedData = [];\r\n        this.renderer._lowBandSmoothedData = [];\r\n\r\n        // prop: bandData\r\n        // Data used to draw error bands or confidence intervals above/below a line.\r\n        //\r\n        // bandData can be input in 3 forms.  jqPlot will figure out which is the\r\n        // low band line and which is the high band line for all forms:\r\n        // \r\n        // A 2 dimensional array like [[yl1, yl2, ...], [yu1, yu2, ...]] where\r\n        // [yl1, yl2, ...] are y values of the lower line and\r\n        // [yu1, yu2, ...] are y values of the upper line.\r\n        // In this case there must be the same number of y data points as data points\r\n        // in the series and the bands will inherit the x values of the series.\r\n        //\r\n        // A 2 dimensional array like [[[xl1, yl1], [xl2, yl2], ...], [[xh1, yh1], [xh2, yh2], ...]]\r\n        // where [xl1, yl1] are x,y data points for the lower line and\r\n        // [xh1, yh1] are x,y data points for the high line.\r\n        // x values do not have to correspond to the x values of the series and can\r\n        // be of any arbitrary length.\r\n        //\r\n        // Can be of form [[yl1, yu1], [yl2, yu2], [yl3, yu3], ...] where\r\n        // there must be 3 or more arrays and there must be the same number of arrays\r\n        // as there are data points in the series.  In this case, \r\n        // [yl1, yu1] specifies the lower and upper y values for the 1st\r\n        // data point and so on.  The bands will inherit the x\r\n        // values from the series.\r\n        this.renderer.bandData = [];\r\n\r\n        // Group: bands\r\n        // Banding around line, e.g error bands or confidence intervals.\r\n        this.renderer.bands = {\r\n            // prop: show\r\n            // true to show the bands.  If bandData or interval is\r\n            // supplied, show will be set to true by default.\r\n            show: false,\r\n            hiData: [],\r\n            lowData: [],\r\n            // prop: color\r\n            // color of lines at top and bottom of bands [default: series color].\r\n            color: this.color,\r\n            // prop: showLines\r\n            // True to show lines at top and bottom of bands [default: false].\r\n            showLines: false,\r\n            // prop: fill\r\n            // True to fill area between bands [default: true].\r\n            fill: true,\r\n            // prop: fillColor\r\n            // css color spec for filled area.  [default: series color].\r\n            fillColor: null,\r\n            _min: null,\r\n            _max: null,\r\n            // prop: interval\r\n            // User specified interval above and below line for bands [default: '3%''].\r\n            // Can be a value like 3 or a string like '3%' \r\n            // or an upper/lower array like [1, -2] or ['2%', '-1.5%']\r\n            interval: '3%'\r\n        };\r\n\r\n\r\n        var lopts = {highlightMouseOver: options.highlightMouseOver, highlightMouseDown: options.highlightMouseDown, highlightColor: options.highlightColor};\r\n        \r\n        delete (options.highlightMouseOver);\r\n        delete (options.highlightMouseDown);\r\n        delete (options.highlightColor);\r\n        \r\n        $.extend(true, this.renderer, options);\r\n\r\n        this.renderer.options = options;\r\n\r\n        // if we are given some band data, and bands aren't explicity set to false in options, turn them on.\r\n        if (this.renderer.bandData.length > 1 && (!options.bands || options.bands.show == null)) {\r\n            this.renderer.bands.show = true;\r\n        }\r\n\r\n        // if we are given an interval, and bands aren't explicity set to false in options, turn them on.\r\n        else if (options.bands && options.bands.show == null && options.bands.interval != null) {\r\n            this.renderer.bands.show = true;\r\n        }\r\n\r\n        // if plot is filled, turn off bands.\r\n        if (this.fill) {\r\n            this.renderer.bands.show = false;\r\n        }\r\n\r\n        if (this.renderer.bands.show) {\r\n            this.renderer.initBands.call(this, this.renderer.options, plot);\r\n        }\r\n\r\n\r\n        // smoothing is not compatible with stacked lines, disable\r\n        if (this._stack) {\r\n            this.renderer.smooth = false;\r\n        }\r\n\r\n        // set the shape renderer options\r\n        var opts = {lineJoin:this.lineJoin, lineCap:this.lineCap, fill:this.fill, isarc:false, strokeStyle:this.color, fillStyle:this.fillColor, lineWidth:this.lineWidth, linePattern:this.linePattern, closePath:this.fill};\r\n        this.renderer.shapeRenderer.init(opts);\r\n\r\n        var shadow_offset = options.shadowOffset;\r\n        // set the shadow renderer options\r\n        if (shadow_offset == null) {\r\n            // scale the shadowOffset to the width of the line.\r\n            if (this.lineWidth > 2.5) {\r\n                shadow_offset = 1.25 * (1 + (Math.atan((this.lineWidth/2.5))/0.785398163 - 1)*0.6);\r\n                // var shadow_offset = this.shadowOffset;\r\n            }\r\n            // for skinny lines, don't make such a big shadow.\r\n            else {\r\n                shadow_offset = 1.25 * Math.atan((this.lineWidth/2.5))/0.785398163;\r\n            }\r\n        }\r\n        \r\n        var sopts = {lineJoin:this.lineJoin, lineCap:this.lineCap, fill:this.fill, isarc:false, angle:this.shadowAngle, offset:shadow_offset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.lineWidth, linePattern:this.linePattern, closePath:this.fill};\r\n        this.renderer.shadowRenderer.init(sopts);\r\n        this._areaPoints = [];\r\n        this._boundingBox = [[],[]];\r\n        \r\n        if (!this.isTrendline && this.fill || this.renderer.bands.show) {\r\n            // Group: Properties\r\n            //        \r\n            // prop: highlightMouseOver\r\n            // True to highlight area on a filled plot when moused over.\r\n            // This must be false to enable highlightMouseDown to highlight when clicking on an area on a filled plot.\r\n            this.highlightMouseOver = true;\r\n            // prop: highlightMouseDown\r\n            // True to highlight when a mouse button is pressed over an area on a filled plot.\r\n            // This will be disabled if highlightMouseOver is true.\r\n            this.highlightMouseDown = false;\r\n            // prop: highlightColor\r\n            // color to use when highlighting an area on a filled plot.\r\n            this.highlightColor = null;\r\n            // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver\r\n            if (lopts.highlightMouseDown && lopts.highlightMouseOver == null) {\r\n                lopts.highlightMouseOver = false;\r\n            }\r\n        \r\n            $.extend(true, this, {highlightMouseOver: lopts.highlightMouseOver, highlightMouseDown: lopts.highlightMouseDown, highlightColor: lopts.highlightColor});\r\n            \r\n            if (!this.highlightColor) {\r\n                var fc = (this.renderer.bands.show) ? this.renderer.bands.fillColor : this.fillColor;\r\n                this.highlightColor = $.jqplot.computeHighlightColors(fc);\r\n            }\r\n            // turn off (disable) the highlighter plugin\r\n            if (this.highlighter) {\r\n                this.highlighter.show = false;\r\n            }\r\n        }\r\n        \r\n        if (!this.isTrendline && plot) {\r\n            plot.plugins.lineRenderer = {};\r\n            plot.postInitHooks.addOnce(postInit);\r\n            plot.postDrawHooks.addOnce(postPlotDraw);\r\n            plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);\r\n            plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);\r\n            plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);\r\n            plot.eventListenerHooks.addOnce('jqplotClick', handleClick);\r\n            plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);\r\n        }\r\n\r\n    };\r\n\r\n    $.jqplot.LineRenderer.prototype.initBands = function(options, plot) {\r\n        // use bandData if no data specified in bands option\r\n        //var bd = this.renderer.bandData;\r\n        var bd = options.bandData || [];\r\n        var bands = this.renderer.bands;\r\n        bands.hiData = [];\r\n        bands.lowData = [];\r\n        var data = this.data;\r\n        bands._max = null;\r\n        bands._min = null;\r\n        // If 2 arrays, and each array greater than 2 elements, assume it is hi and low data bands of y values.\r\n        if (bd.length == 2) {\r\n            // Do we have an array of x,y values?\r\n            // like [[[1,1], [2,4], [3,3]], [[1,3], [2,6], [3,5]]]\r\n            if ($.isArray(bd[0][0])) {\r\n                // since an arbitrary array of points, spin through all of them to determine max and min lines.\r\n\r\n                var p;\r\n                var bdminidx = 0, bdmaxidx = 0;\r\n                for (var i = 0, l = bd[0].length; i<l; i++) {\r\n                    p = bd[0][i];\r\n                    if ((p[1] != null && p[1] > bands._max) || bands._max == null) {\r\n                        bands._max = p[1];\r\n                    }\r\n                    if ((p[1] != null && p[1] < bands._min) || bands._min == null) {\r\n                        bands._min = p[1];\r\n                    }\r\n                }\r\n                for (var i = 0, l = bd[1].length; i<l; i++) {\r\n                    p = bd[1][i];\r\n                    if ((p[1] != null && p[1] > bands._max) || bands._max == null) {\r\n                        bands._max = p[1];\r\n                        bdmaxidx = 1;\r\n                    }\r\n                    if ((p[1] != null && p[1] < bands._min) || bands._min == null) {\r\n                        bands._min = p[1];\r\n                        bdminidx = 1;\r\n                    }\r\n                }\r\n\r\n                if (bdmaxidx === bdminidx) {\r\n                    bands.show = false;\r\n                }\r\n\r\n                bands.hiData = bd[bdmaxidx];\r\n                bands.lowData = bd[bdminidx];\r\n            }\r\n            // else data is arrays of y values\r\n            // like [[1,4,3], [3,6,5]]\r\n            // must have same number of band data points as points in series\r\n            else if (bd[0].length === data.length && bd[1].length === data.length) {\r\n                var hi = (bd[0][0] > bd[1][0]) ? 0 : 1;\r\n                var low = (hi) ? 0 : 1;\r\n                for (var i=0, l=data.length; i < l; i++) {\r\n                    bands.hiData.push([data[i][0], bd[hi][i]]);\r\n                    bands.lowData.push([data[i][0], bd[low][i]]);\r\n                }\r\n            }\r\n\r\n            // we don't have proper data array, don't show bands.\r\n            else {\r\n                bands.show = false;\r\n            }\r\n        }\r\n\r\n        // if more than 2 arrays, have arrays of [ylow, yhi] values.\r\n        // note, can't distinguish case of [[ylow, yhi], [ylow, yhi]] from [[ylow, ylow], [yhi, yhi]]\r\n        // this is assumed to be of the latter form.\r\n        else if (bd.length > 2 && !$.isArray(bd[0][0])) {\r\n            var hi = (bd[0][0] > bd[0][1]) ? 0 : 1;\r\n            var low = (hi) ? 0 : 1;\r\n            for (var i=0, l=bd.length; i<l; i++) {\r\n                bands.hiData.push([data[i][0], bd[i][hi]]);\r\n                bands.lowData.push([data[i][0], bd[i][low]]);\r\n            }\r\n        }\r\n\r\n        // don't have proper data, auto calculate\r\n        else {\r\n            var intrv = bands.interval;\r\n            var a = null;\r\n            var b = null;\r\n            var afunc = null;\r\n            var bfunc = null;\r\n\r\n            if ($.isArray(intrv)) {\r\n                a = intrv[0];\r\n                b = intrv[1];\r\n            }\r\n            else {\r\n                a = intrv;\r\n            }\r\n\r\n            if (isNaN(a)) {\r\n                // we have a string\r\n                if (a.charAt(a.length - 1) === '%') {\r\n                    afunc = 'multiply';\r\n                    a = parseFloat(a)/100 + 1;\r\n                }\r\n            }\r\n\r\n            else {\r\n                a = parseFloat(a);\r\n                afunc = 'add';\r\n            }\r\n\r\n            if (b !== null && isNaN(b)) {\r\n                // we have a string\r\n                if (b.charAt(b.length - 1) === '%') {\r\n                    bfunc = 'multiply';\r\n                    b = parseFloat(b)/100 + 1;\r\n                }\r\n            }\r\n\r\n            else if (b !== null) {\r\n                b = parseFloat(b);\r\n                bfunc = 'add';\r\n            }\r\n\r\n            if (a !== null) {\r\n                if (b === null) {\r\n                    b = -a;\r\n                    bfunc = afunc;\r\n                    if (bfunc === 'multiply') {\r\n                        b += 2;\r\n                    }\r\n                }\r\n\r\n                // make sure a always applies to hi band.\r\n                if (a < b) {\r\n                    var temp = a;\r\n                    a = b;\r\n                    b = temp;\r\n                    temp = afunc;\r\n                    afunc = bfunc;\r\n                    bfunc = temp;\r\n                }\r\n\r\n                for (var i=0, l = data.length; i < l; i++) {\r\n                    switch (afunc) {\r\n                        case 'add':\r\n                            bands.hiData.push([data[i][0], data[i][1] + a]);\r\n                            break;\r\n                        case 'multiply':\r\n                            bands.hiData.push([data[i][0], data[i][1] * a]);\r\n                            break;\r\n                    }\r\n                    switch (bfunc) {\r\n                        case 'add':\r\n                            bands.lowData.push([data[i][0], data[i][1] + b]);\r\n                            break;\r\n                        case 'multiply':\r\n                            bands.lowData.push([data[i][0], data[i][1] * b]);\r\n                            break;\r\n                    }\r\n                }\r\n            }\r\n\r\n            else {\r\n                bands.show = false;\r\n            }\r\n        }\r\n\r\n        var hd = bands.hiData;\r\n        var ld = bands.lowData;\r\n        for (var i = 0, l = hd.length; i<l; i++) {\r\n            if ((hd[i][1] != null && hd[i][1] > bands._max) || bands._max == null) {\r\n                bands._max = hd[i][1];\r\n            }\r\n        }\r\n        for (var i = 0, l = ld.length; i<l; i++) {\r\n            if ((ld[i][1] != null && ld[i][1] < bands._min) || bands._min == null) {\r\n                bands._min = ld[i][1];\r\n            }\r\n        }\r\n\r\n        // one last check for proper data\r\n        // these don't apply any more since allowing arbitrary x,y values\r\n        // if (bands.hiData.length != bands.lowData.length) {\r\n        //     bands.show = false;\r\n        // }\r\n\r\n        // if (bands.hiData.length != this.data.length) {\r\n        //     bands.show = false;\r\n        // }\r\n\r\n        if (bands.fillColor === null) {\r\n            var c = $.jqplot.getColorComponents(bands.color);\r\n            // now adjust alpha to differentiate fill\r\n            c[3] = c[3] * 0.5;\r\n            bands.fillColor = 'rgba(' + c[0] +', '+ c[1] +', '+ c[2] +', '+ c[3] + ')';\r\n        }\r\n    };\r\n\r\n    function getSteps (d, f) {\r\n        return (3.4182054+f) * Math.pow(d, -0.3534992);\r\n    }\r\n\r\n    function computeSteps (d1, d2) {\r\n        var s = Math.sqrt(Math.pow((d2[0]- d1[0]), 2) + Math.pow ((d2[1] - d1[1]), 2));\r\n        return 5.7648 * Math.log(s) + 7.4456;\r\n    }\r\n\r\n    function tanh (x) {\r\n        var a = (Math.exp(2*x) - 1) / (Math.exp(2*x) + 1);\r\n        return a;\r\n    }\r\n\r\n    //////////\r\n    // computeConstrainedSmoothedData\r\n    // An implementation of the constrained cubic spline interpolation\r\n    // method as presented in:\r\n    //\r\n    // Kruger, CJC, Constrained Cubic Spine Interpolation for Chemical Engineering Applications\r\n    // http://www.korf.co.uk/spline.pdf\r\n    //\r\n    // The implementation below borrows heavily from the sample Visual Basic\r\n    // implementation by CJC Kruger found in http://www.korf.co.uk/spline.xls\r\n    //\r\n    /////////\r\n\r\n    // called with scope of series\r\n    function computeConstrainedSmoothedData (gd) {\r\n        var smooth = this.renderer.smooth;\r\n        var dim = this.canvas.getWidth();\r\n        var xp = this._xaxis.series_p2u;\r\n        var yp = this._yaxis.series_p2u; \r\n        var steps =null;\r\n        var _steps = null;\r\n        var dist = gd.length/dim;\r\n        var _smoothedData = [];\r\n        var _smoothedPlotData = [];\r\n\r\n        if (!isNaN(parseFloat(smooth))) {\r\n            steps = parseFloat(smooth);\r\n        }\r\n        else {\r\n            steps = getSteps(dist, 0.5);\r\n        }\r\n\r\n        var yy = [];\r\n        var xx = [];\r\n\r\n        for (var i=0, l = gd.length; i<l; i++) {\r\n            yy.push(gd[i][1]);\r\n            xx.push(gd[i][0]);\r\n        }\r\n\r\n        function dxx(x1, x0) {\r\n            if (x1 - x0 == 0) {\r\n                return Math.pow(10,10);\r\n            }\r\n            else {\r\n                return x1 - x0;\r\n            }\r\n        }\r\n\r\n        var A, B, C, D;\r\n        // loop through each line segment.  Have # points - 1 line segments.  Nmber segments starting at 1.\r\n        var nmax = gd.length - 1;\r\n        for (var num = 1, gdl = gd.length; num<gdl; num++) {\r\n            var gxx = [];\r\n            var ggxx = [];\r\n            // point at each end of segment.\r\n            for (var j = 0; j < 2; j++) {\r\n                var i = num - 1 + j; // point number, 0 to # points.\r\n\r\n                if (i == 0 || i == nmax) {\r\n                    gxx[j] = Math.pow(10, 10);\r\n                }\r\n                else if (yy[i+1] - yy[i] == 0 || yy[i] - yy[i-1] == 0) {\r\n                    gxx[j] = 0;\r\n                }\r\n                else if (((xx[i+1] - xx[i]) / (yy[i+1] - yy[i]) + (xx[i] - xx[i-1]) / (yy[i] - yy[i-1])) == 0 ) {\r\n                    gxx[j] = 0;\r\n                }\r\n                else if ( (yy[i+1] - yy[i]) * (yy[i] - yy[i-1]) < 0 ) {\r\n                    gxx[j] = 0;\r\n                }\r\n\r\n                else {\r\n                    gxx[j] = 2 / (dxx(xx[i + 1], xx[i]) / (yy[i + 1] - yy[i]) + dxx(xx[i], xx[i - 1]) / (yy[i] - yy[i - 1]));\r\n                }\r\n            }\r\n\r\n            // Reset first derivative (slope) at first and last point\r\n            if (num == 1) {\r\n                // First point has 0 2nd derivative\r\n                gxx[0] = 3 / 2 * (yy[1] - yy[0]) / dxx(xx[1], xx[0]) - gxx[1] / 2;\r\n            }\r\n            else if (num == nmax) {\r\n                // Last point has 0 2nd derivative\r\n                gxx[1] = 3 / 2 * (yy[nmax] - yy[nmax - 1]) / dxx(xx[nmax], xx[nmax - 1]) - gxx[0] / 2;\r\n            }   \r\n\r\n            // Calc second derivative at points\r\n            ggxx[0] = -2 * (gxx[1] + 2 * gxx[0]) / dxx(xx[num], xx[num - 1]) + 6 * (yy[num] - yy[num - 1]) / Math.pow(dxx(xx[num], xx[num - 1]), 2);\r\n            ggxx[1] = 2 * (2 * gxx[1] + gxx[0]) / dxx(xx[num], xx[num - 1]) - 6 * (yy[num] - yy[num - 1]) / Math.pow(dxx(xx[num], xx[num - 1]), 2);\r\n\r\n            // Calc constants for cubic interpolation\r\n            D = 1 / 6 * (ggxx[1] - ggxx[0]) / dxx(xx[num], xx[num - 1]);\r\n            C = 1 / 2 * (xx[num] * ggxx[0] - xx[num - 1] * ggxx[1]) / dxx(xx[num], xx[num - 1]);\r\n            B = (yy[num] - yy[num - 1] - C * (Math.pow(xx[num], 2) - Math.pow(xx[num - 1], 2)) - D * (Math.pow(xx[num], 3) - Math.pow(xx[num - 1], 3))) / dxx(xx[num], xx[num - 1]);\r\n            A = yy[num - 1] - B * xx[num - 1] - C * Math.pow(xx[num - 1], 2) - D * Math.pow(xx[num - 1], 3);\r\n\r\n            var increment = (xx[num] - xx[num - 1]) / steps;\r\n            var temp, tempx;\r\n\r\n            for (var j = 0, l = steps; j < l; j++) {\r\n                temp = [];\r\n                tempx = xx[num - 1] + j * increment;\r\n                temp.push(tempx);\r\n                temp.push(A + B * tempx + C * Math.pow(tempx, 2) + D * Math.pow(tempx, 3));\r\n                _smoothedData.push(temp);\r\n                _smoothedPlotData.push([xp(temp[0]), yp(temp[1])]);\r\n            }\r\n        }\r\n\r\n        _smoothedData.push(gd[i]);\r\n        _smoothedPlotData.push([xp(gd[i][0]), yp(gd[i][1])]);\r\n\r\n        return [_smoothedData, _smoothedPlotData];\r\n    }\r\n\r\n    ///////\r\n    // computeHermiteSmoothedData\r\n    // A hermite spline smoothing of the plot data.\r\n    // This implementation is derived from the one posted\r\n    // by krypin on the jqplot-users mailing list:\r\n    //\r\n    // http://groups.google.com/group/jqplot-users/browse_thread/thread/748be6a445723cea?pli=1\r\n    //\r\n    // with a blog post:\r\n    //\r\n    // http://blog.statscollector.com/a-plugin-renderer-for-jqplot-to-draw-a-hermite-spline/\r\n    //\r\n    // and download of the original plugin:\r\n    //\r\n    // http://blog.statscollector.com/wp-content/uploads/2010/02/jqplot.hermiteSplineRenderer.js\r\n    //////////\r\n\r\n    // called with scope of series\r\n    function computeHermiteSmoothedData (gd) {\r\n        var smooth = this.renderer.smooth;\r\n        var tension = this.renderer.tension;\r\n        var dim = this.canvas.getWidth();\r\n        var xp = this._xaxis.series_p2u;\r\n        var yp = this._yaxis.series_p2u; \r\n        var steps =null;\r\n        var _steps = null;\r\n        var a = null;\r\n        var a1 = null;\r\n        var a2 = null;\r\n        var slope = null;\r\n        var slope2 = null;\r\n        var temp = null;\r\n        var t, s, h1, h2, h3, h4;\r\n        var TiX, TiY, Ti1X, Ti1Y;\r\n        var pX, pY, p;\r\n        var sd = [];\r\n        var spd = [];\r\n        var dist = gd.length/dim;\r\n        var min, max, stretch, scale, shift;\r\n        var _smoothedData = [];\r\n        var _smoothedPlotData = [];\r\n        if (!isNaN(parseFloat(smooth))) {\r\n            steps = parseFloat(smooth);\r\n        }\r\n        else {\r\n            steps = getSteps(dist, 0.5);\r\n        }\r\n        if (!isNaN(parseFloat(tension))) {\r\n            tension = parseFloat(tension);\r\n        }\r\n\r\n        for (var i=0, l = gd.length-1; i < l; i++) {\r\n\r\n            if (tension === null) {\r\n                slope = Math.abs((gd[i+1][1] - gd[i][1]) / (gd[i+1][0] - gd[i][0]));\r\n\r\n                min = 0.3;\r\n                max = 0.6;\r\n                stretch = (max - min)/2.0;\r\n                scale = 2.5;\r\n                shift = -1.4;\r\n\r\n                temp = slope/scale + shift;\r\n\r\n                a1 = stretch * tanh(temp) - stretch * tanh(shift) + min;\r\n\r\n                // if have both left and right line segments, will use  minimum tension. \r\n                if (i > 0) {\r\n                    slope2 = Math.abs((gd[i][1] - gd[i-1][1]) / (gd[i][0] - gd[i-1][0]));\r\n                }\r\n                temp = slope2/scale + shift;\r\n\r\n                a2 = stretch * tanh(temp) - stretch * tanh(shift) + min;\r\n\r\n                a = (a1 + a2)/2.0;\r\n\r\n            }\r\n            else {\r\n                a = tension;\r\n            }\r\n            for (t=0; t < steps; t++) {\r\n                s = t / steps;\r\n                h1 = (1 + 2*s)*Math.pow((1-s),2);\r\n                h2 = s*Math.pow((1-s),2);\r\n                h3 = Math.pow(s,2)*(3-2*s);\r\n                h4 = Math.pow(s,2)*(s-1);     \r\n                \r\n                if (gd[i-1]) {  \r\n                    TiX = a * (gd[i+1][0] - gd[i-1][0]); \r\n                    TiY = a * (gd[i+1][1] - gd[i-1][1]);\r\n                } else {\r\n                    TiX = a * (gd[i+1][0] - gd[i][0]); \r\n                    TiY = a * (gd[i+1][1] - gd[i][1]);                                  \r\n                }\r\n                if (gd[i+2]) {  \r\n                    Ti1X = a * (gd[i+2][0] - gd[i][0]); \r\n                    Ti1Y = a * (gd[i+2][1] - gd[i][1]);\r\n                } else {\r\n                    Ti1X = a * (gd[i+1][0] - gd[i][0]); \r\n                    Ti1Y = a * (gd[i+1][1] - gd[i][1]);                                 \r\n                }\r\n                \r\n                pX = h1*gd[i][0] + h3*gd[i+1][0] + h2*TiX + h4*Ti1X;\r\n                pY = h1*gd[i][1] + h3*gd[i+1][1] + h2*TiY + h4*Ti1Y;\r\n                p = [pX, pY];\r\n\r\n                _smoothedData.push(p);\r\n                _smoothedPlotData.push([xp(pX), yp(pY)]);\r\n            }\r\n        }\r\n        _smoothedData.push(gd[l]);\r\n        _smoothedPlotData.push([xp(gd[l][0]), yp(gd[l][1])]);\r\n\r\n        return [_smoothedData, _smoothedPlotData];\r\n    }\r\n    \r\n    // setGridData\r\n    // converts the user data values to grid coordinates and stores them\r\n    // in the gridData array.\r\n    // Called with scope of a series.\r\n    $.jqplot.LineRenderer.prototype.setGridData = function(plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var data = this._plotData;\r\n        var pdata = this._prevPlotData;\r\n        this.gridData = [];\r\n        this._prevGridData = [];\r\n        this.renderer._smoothedData = [];\r\n        this.renderer._smoothedPlotData = [];\r\n        this.renderer._hiBandGridData = [];\r\n        this.renderer._lowBandGridData = [];\r\n        this.renderer._hiBandSmoothedData = [];\r\n        this.renderer._lowBandSmoothedData = [];\r\n        var bands = this.renderer.bands;\r\n        var hasNull = false;\r\n        for (var i=0, l=data.length; i < l; i++) {\r\n            // if not a line series or if no nulls in data, push the converted point onto the array.\r\n            if (data[i][0] != null && data[i][1] != null) {\r\n                this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]);\r\n            }\r\n            // else if there is a null, preserve it.\r\n            else if (data[i][0] == null) {\r\n                hasNull = true;\r\n                this.gridData.push([null, yp.call(this._yaxis, data[i][1])]);\r\n            }\r\n            else if (data[i][1] == null) {\r\n                hasNull = true;\r\n                this.gridData.push([xp.call(this._xaxis, data[i][0]), null]);\r\n            }\r\n            // if not a line series or if no nulls in data, push the converted point onto the array.\r\n            if (pdata[i] != null && pdata[i][0] != null && pdata[i][1] != null) {\r\n                this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), yp.call(this._yaxis, pdata[i][1])]);\r\n            }\r\n            // else if there is a null, preserve it.\r\n            else if (pdata[i] != null && pdata[i][0] == null) {\r\n                this._prevGridData.push([null, yp.call(this._yaxis, pdata[i][1])]);\r\n            }  \r\n            else if (pdata[i] != null && pdata[i][0] != null && pdata[i][1] == null) {\r\n                this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), null]);\r\n            }\r\n        }\r\n\r\n        // don't do smoothing or bands on broken lines.\r\n        if (hasNull) {\r\n            this.renderer.smooth = false;\r\n            if (this._type === 'line') {\r\n                bands.show = false;\r\n            }\r\n        }\r\n\r\n        if (this._type === 'line' && bands.show) {\r\n            for (var i=0, l=bands.hiData.length; i<l; i++) {\r\n                this.renderer._hiBandGridData.push([xp.call(this._xaxis, bands.hiData[i][0]), yp.call(this._yaxis, bands.hiData[i][1])]);\r\n            }\r\n            for (var i=0, l=bands.lowData.length; i<l; i++) {\r\n                this.renderer._lowBandGridData.push([xp.call(this._xaxis, bands.lowData[i][0]), yp.call(this._yaxis, bands.lowData[i][1])]);\r\n            }\r\n        }\r\n\r\n        // calculate smoothed data if enough points and no nulls\r\n        if (this._type === 'line' && this.renderer.smooth && this.gridData.length > 2) {\r\n            var ret;\r\n            if (this.renderer.constrainSmoothing) {\r\n                ret = computeConstrainedSmoothedData.call(this, this.gridData);\r\n                this.renderer._smoothedData = ret[0];\r\n                this.renderer._smoothedPlotData = ret[1];\r\n\r\n                if (bands.show) {\r\n                    ret = computeConstrainedSmoothedData.call(this, this.renderer._hiBandGridData);\r\n                    this.renderer._hiBandSmoothedData = ret[0];\r\n                    ret = computeConstrainedSmoothedData.call(this, this.renderer._lowBandGridData);\r\n                    this.renderer._lowBandSmoothedData = ret[0];\r\n                }\r\n\r\n                ret = null;\r\n            }\r\n            else {\r\n                ret = computeHermiteSmoothedData.call(this, this.gridData);\r\n                this.renderer._smoothedData = ret[0];\r\n                this.renderer._smoothedPlotData = ret[1];\r\n\r\n                if (bands.show) {\r\n                    ret = computeHermiteSmoothedData.call(this, this.renderer._hiBandGridData);\r\n                    this.renderer._hiBandSmoothedData = ret[0];\r\n                    ret = computeHermiteSmoothedData.call(this, this.renderer._lowBandGridData);\r\n                    this.renderer._lowBandSmoothedData = ret[0];\r\n                }\r\n\r\n                ret = null;\r\n            }\r\n        }\r\n    };\r\n    \r\n    // makeGridData\r\n    // converts any arbitrary data values to grid coordinates and\r\n    // returns them.  This method exists so that plugins can use a series'\r\n    // linerenderer to generate grid data points without overwriting the\r\n    // grid data associated with that series.\r\n    // Called with scope of a series.\r\n    $.jqplot.LineRenderer.prototype.makeGridData = function(data, plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var gd = [];\r\n        var pgd = [];\r\n        this.renderer._smoothedData = [];\r\n        this.renderer._smoothedPlotData = [];\r\n        this.renderer._hiBandGridData = [];\r\n        this.renderer._lowBandGridData = [];\r\n        this.renderer._hiBandSmoothedData = [];\r\n        this.renderer._lowBandSmoothedData = [];\r\n        var bands = this.renderer.bands;\r\n        var hasNull = false;\r\n        for (var i=0; i<data.length; i++) {\r\n            // if not a line series or if no nulls in data, push the converted point onto the array.\r\n            if (data[i][0] != null && data[i][1] != null) {\r\n                if (this.step && i>0) {\r\n                    gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i-1][1])]);\r\n                }\r\n                gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]);\r\n            }\r\n            // else if there is a null, preserve it.\r\n            else if (data[i][0] == null) {\r\n                hasNull = true;\r\n                gd.push([null, yp.call(this._yaxis, data[i][1])]);\r\n            }\r\n            else if (data[i][1] == null) {\r\n                hasNull = true;\r\n                gd.push([xp.call(this._xaxis, data[i][0]), null]);\r\n            }\r\n        }\r\n\r\n        // don't do smoothing or bands on broken lines.\r\n        if (hasNull) {\r\n            this.renderer.smooth = false;\r\n            if (this._type === 'line') {\r\n                bands.show = false;\r\n            }\r\n        }\r\n\r\n        if (this._type === 'line' && bands.show) {\r\n            for (var i=0, l=bands.hiData.length; i<l; i++) {\r\n                this.renderer._hiBandGridData.push([xp.call(this._xaxis, bands.hiData[i][0]), yp.call(this._yaxis, bands.hiData[i][1])]);\r\n            }\r\n            for (var i=0, l=bands.lowData.length; i<l; i++) {\r\n                this.renderer._lowBandGridData.push([xp.call(this._xaxis, bands.lowData[i][0]), yp.call(this._yaxis, bands.lowData[i][1])]);\r\n            }\r\n        }\r\n\r\n        if (this._type === 'line' && this.renderer.smooth && gd.length > 2) {\r\n            var ret;\r\n            if (this.renderer.constrainSmoothing) {\r\n                ret = computeConstrainedSmoothedData.call(this, gd);\r\n                this.renderer._smoothedData = ret[0];\r\n                this.renderer._smoothedPlotData = ret[1];\r\n\r\n                if (bands.show) {\r\n                    ret = computeConstrainedSmoothedData.call(this, this.renderer._hiBandGridData);\r\n                    this.renderer._hiBandSmoothedData = ret[0];\r\n                    ret = computeConstrainedSmoothedData.call(this, this.renderer._lowBandGridData);\r\n                    this.renderer._lowBandSmoothedData = ret[0];\r\n                }\r\n\r\n                ret = null;\r\n            }\r\n            else {\r\n                ret = computeHermiteSmoothedData.call(this, gd);\r\n                this.renderer._smoothedData = ret[0];\r\n                this.renderer._smoothedPlotData = ret[1];\r\n\r\n                if (bands.show) {\r\n                    ret = computeHermiteSmoothedData.call(this, this.renderer._hiBandGridData);\r\n                    this.renderer._hiBandSmoothedData = ret[0];\r\n                    ret = computeHermiteSmoothedData.call(this, this.renderer._lowBandGridData);\r\n                    this.renderer._lowBandSmoothedData = ret[0];\r\n                }\r\n\r\n                ret = null;\r\n            }\r\n        }\r\n        return gd;\r\n    };\r\n    \r\n\r\n    // called within scope of series.\r\n    $.jqplot.LineRenderer.prototype.draw = function(ctx, gd, options, plot) {\r\n        var i;\r\n        // get a copy of the options, so we don't modify the original object.\r\n        var opts = $.extend(true, {}, options);\r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        var fillAndStroke = (opts.fillAndStroke != undefined) ? opts.fillAndStroke : this.fillAndStroke;\r\n        var xmin, ymin, xmax, ymax;\r\n        ctx.save();\r\n        if (gd.length) {\r\n            if (showLine) {\r\n                // if we fill, we'll have to add points to close the curve.\r\n                if (fill) {\r\n                    if (this.fillToZero) { \r\n                        // have to break line up into shapes at axis crossings\r\n                        var negativeColor = this.negativeColor;\r\n                        if (! this.useNegativeColors) {\r\n                            negativeColor = opts.fillStyle;\r\n                        }\r\n                        var isnegative = false;\r\n                        var posfs = opts.fillStyle;\r\n                    \r\n                        // if stoking line as well as filling, get a copy of line data.\r\n                        if (fillAndStroke) {\r\n                            var fasgd = gd.slice(0);\r\n                        }\r\n                        // if not stacked, fill down to axis\r\n                        if (this.index == 0 || !this._stack) {\r\n                        \r\n                            var tempgd = [];\r\n                            var pd = (this.renderer.smooth) ? this.renderer._smoothedPlotData : this._plotData;\r\n                            this._areaPoints = [];\r\n                            var pyzero = this._yaxis.series_u2p(this.fillToValue);\r\n                            var pxzero = this._xaxis.series_u2p(this.fillToValue);\r\n\r\n                            opts.closePath = true;\r\n                            \r\n                            if (this.fillAxis == 'y') {\r\n                                tempgd.push([gd[0][0], pyzero]);\r\n                                this._areaPoints.push([gd[0][0], pyzero]);\r\n                                \r\n                                for (var i=0; i<gd.length-1; i++) {\r\n                                    tempgd.push(gd[i]);\r\n                                    this._areaPoints.push(gd[i]);\r\n                                    // do we have an axis crossing?\r\n                                    if (pd[i][1] * pd[i+1][1] <= 0) {\r\n                                        if (pd[i][1] < 0) {\r\n                                            isnegative = true;\r\n                                            opts.fillStyle = negativeColor;\r\n                                        }\r\n                                        else {\r\n                                            isnegative = false;\r\n                                            opts.fillStyle = posfs;\r\n                                        }\r\n                                        \r\n                                        var xintercept = gd[i][0] + (gd[i+1][0] - gd[i][0]) * (pyzero-gd[i][1])/(gd[i+1][1] - gd[i][1]);\r\n                                        tempgd.push([xintercept, pyzero]);\r\n                                        this._areaPoints.push([xintercept, pyzero]);\r\n                                        // now draw this shape and shadow.\r\n                                        if (shadow) {\r\n                                            this.renderer.shadowRenderer.draw(ctx, tempgd, opts);\r\n                                        }\r\n                                        this.renderer.shapeRenderer.draw(ctx, tempgd, opts);\r\n                                        // now empty temp array and continue\r\n                                        tempgd = [[xintercept, pyzero]];\r\n                                        // this._areaPoints = [[xintercept, pyzero]];\r\n                                    }   \r\n                                }\r\n                                if (pd[gd.length-1][1] < 0) {\r\n                                    isnegative = true;\r\n                                    opts.fillStyle = negativeColor;\r\n                                }\r\n                                else {\r\n                                    isnegative = false;\r\n                                    opts.fillStyle = posfs;\r\n                                }\r\n                                tempgd.push(gd[gd.length-1]);\r\n                                this._areaPoints.push(gd[gd.length-1]);\r\n                                tempgd.push([gd[gd.length-1][0], pyzero]); \r\n                                this._areaPoints.push([gd[gd.length-1][0], pyzero]); \r\n                            }\r\n                            // now draw the last area.\r\n                            if (shadow) {\r\n                                this.renderer.shadowRenderer.draw(ctx, tempgd, opts);\r\n                            }\r\n                            this.renderer.shapeRenderer.draw(ctx, tempgd, opts);\r\n                            \r\n                            \r\n                            // var gridymin = this._yaxis.series_u2p(0);\r\n                            // // IE doesn't return new length on unshift\r\n                            // gd.unshift([gd[0][0], gridymin]);\r\n                            // len = gd.length;\r\n                            // gd.push([gd[len - 1][0], gridymin]);                   \r\n                        }\r\n                        // if stacked, fill to line below \r\n                        else {\r\n                            var prev = this._prevGridData;\r\n                            for (var i=prev.length; i>0; i--) {\r\n                                gd.push(prev[i-1]);\r\n                                // this._areaPoints.push(prev[i-1]);\r\n                            }\r\n                            if (shadow) {\r\n                                this.renderer.shadowRenderer.draw(ctx, gd, opts);\r\n                            }\r\n                            this._areaPoints = gd;\r\n                            this.renderer.shapeRenderer.draw(ctx, gd, opts);\r\n                        }\r\n                    }\r\n                    /////////////////////////\r\n                    // Not filled to zero\r\n                    ////////////////////////\r\n                    else {                    \r\n                        // if stoking line as well as filling, get a copy of line data.\r\n                        if (fillAndStroke) {\r\n                            var fasgd = gd.slice(0);\r\n                        }\r\n                        // if not stacked, fill down to axis\r\n                        if (this.index == 0 || !this._stack) {\r\n                            // var gridymin = this._yaxis.series_u2p(this._yaxis.min) - this.gridBorderWidth / 2;\r\n                            var gridymin = ctx.canvas.height;\r\n                            // IE doesn't return new length on unshift\r\n                            gd.unshift([gd[0][0], gridymin]);\r\n                            var len = gd.length;\r\n                            gd.push([gd[len - 1][0], gridymin]);                   \r\n                        }\r\n                        // if stacked, fill to line below \r\n                        else {\r\n                            var prev = this._prevGridData;\r\n                            for (var i=prev.length; i>0; i--) {\r\n                                gd.push(prev[i-1]);\r\n                            }\r\n                        }\r\n                        this._areaPoints = gd;\r\n                        \r\n                        if (shadow) {\r\n                            this.renderer.shadowRenderer.draw(ctx, gd, opts);\r\n                        }\r\n            \r\n                        this.renderer.shapeRenderer.draw(ctx, gd, opts);                        \r\n                    }\r\n                    if (fillAndStroke) {\r\n                        var fasopts = $.extend(true, {}, opts, {fill:false, closePath:false});\r\n                        this.renderer.shapeRenderer.draw(ctx, fasgd, fasopts);\r\n                        //////////\r\n                        // TODO: figure out some way to do shadows nicely\r\n                        // if (shadow) {\r\n                        //     this.renderer.shadowRenderer.draw(ctx, fasgd, fasopts);\r\n                        // }\r\n                        // now draw the markers\r\n                        if (this.markerRenderer.show) {\r\n                            if (this.renderer.smooth) {\r\n                                fasgd = this.gridData;\r\n                            }\r\n                            for (i=0; i<fasgd.length; i++) {\r\n                                this.markerRenderer.draw(fasgd[i][0], fasgd[i][1], ctx, opts.markerOptions);\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                else {\r\n\r\n                    if (this.renderer.bands.show) {\r\n                        var bdat;\r\n                        var bopts = $.extend(true, {}, opts);\r\n                        if (this.renderer.bands.showLines) {\r\n                            bdat = (this.renderer.smooth) ? this.renderer._hiBandSmoothedData : this.renderer._hiBandGridData;\r\n                            this.renderer.shapeRenderer.draw(ctx, bdat, opts);\r\n                            bdat = (this.renderer.smooth) ? this.renderer._lowBandSmoothedData : this.renderer._lowBandGridData;\r\n                            this.renderer.shapeRenderer.draw(ctx, bdat, bopts);\r\n                        }\r\n\r\n                        if (this.renderer.bands.fill) {\r\n                            if (this.renderer.smooth) {\r\n                                bdat = this.renderer._hiBandSmoothedData.concat(this.renderer._lowBandSmoothedData.reverse());\r\n                            }\r\n                            else {\r\n                                bdat = this.renderer._hiBandGridData.concat(this.renderer._lowBandGridData.reverse());\r\n                            }\r\n                            this._areaPoints = bdat;\r\n                            bopts.closePath = true;\r\n                            bopts.fill = true;\r\n                            bopts.fillStyle = this.renderer.bands.fillColor;\r\n                            this.renderer.shapeRenderer.draw(ctx, bdat, bopts);\r\n                        }\r\n                    }\r\n\r\n                    if (shadow) {\r\n                        this.renderer.shadowRenderer.draw(ctx, gd, opts);\r\n                    }\r\n    \r\n                    this.renderer.shapeRenderer.draw(ctx, gd, opts);\r\n                }\r\n            }\r\n            // calculate the bounding box\r\n            var xmin = xmax = ymin = ymax = null;\r\n            for (i=0; i<this._areaPoints.length; i++) {\r\n                var p = this._areaPoints[i];\r\n                if (xmin > p[0] || xmin == null) {\r\n                    xmin = p[0];\r\n                }\r\n                if (ymax < p[1] || ymax == null) {\r\n                    ymax = p[1];\r\n                }\r\n                if (xmax < p[0] || xmax == null) {\r\n                    xmax = p[0];\r\n                }\r\n                if (ymin > p[1] || ymin == null) {\r\n                    ymin = p[1];\r\n                }\r\n            }\r\n\r\n            if (this.type === 'line' && this.renderer.bands.show) {\r\n                ymax = this._yaxis.series_u2p(this.renderer.bands._min);\r\n                ymin = this._yaxis.series_u2p(this.renderer.bands._max);\r\n            }\r\n\r\n            this._boundingBox = [[xmin, ymax], [xmax, ymin]];\r\n        \r\n            // now draw the markers\r\n            if (this.markerRenderer.show && !fill) {\r\n                if (this.renderer.smooth) {\r\n                    gd = this.gridData;\r\n                }\r\n                for (i=0; i<gd.length; i++) {\r\n                    if (gd[i][0] != null && gd[i][1] != null) {\r\n                        this.markerRenderer.draw(gd[i][0], gd[i][1], ctx, opts.markerOptions);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        \r\n        ctx.restore();\r\n    };  \r\n    \r\n    $.jqplot.LineRenderer.prototype.drawShadow = function(ctx, gd, options) {\r\n        // This is a no-op, shadows drawn with lines.\r\n    };\r\n    \r\n    // called with scope of plot.\r\n    // make sure to not leave anything highlighted.\r\n    function postInit(target, data, options) {\r\n        for (var i=0; i<this.series.length; i++) {\r\n            if (this.series[i].renderer.constructor == $.jqplot.LineRenderer) {\r\n                // don't allow mouseover and mousedown at same time.\r\n                if (this.series[i].highlightMouseOver) {\r\n                    this.series[i].highlightMouseDown = false;\r\n                }\r\n            }\r\n        }\r\n    }  \r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    function postPlotDraw() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.lineRenderer && this.plugins.lineRenderer.highlightCanvas) {\r\n          this.plugins.lineRenderer.highlightCanvas.resetCanvas();\r\n          this.plugins.lineRenderer.highlightCanvas = null;\r\n        }\r\n        \r\n        this.plugins.lineRenderer.highlightedSeriesIndex = null;\r\n        this.plugins.lineRenderer.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        \r\n        this.eventCanvas._elem.before(this.plugins.lineRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-lineRenderer-highlight-canvas', this._plotDimensions, this));\r\n        this.plugins.lineRenderer.highlightCanvas.setContext();\r\n        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });\r\n    } \r\n    \r\n    function highlight (plot, sidx, pidx, points) {\r\n        var s = plot.series[sidx];\r\n        var canvas = plot.plugins.lineRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        s._highlightedPoint = pidx;\r\n        plot.plugins.lineRenderer.highlightedSeriesIndex = sidx;\r\n        var opts = {fillStyle: s.highlightColor};\r\n        if (s.type === 'line' && s.renderer.bands.show) {\r\n            opts.fill = true;\r\n            opts.closePath = true;\r\n        }\r\n        s.renderer.shapeRenderer.draw(canvas._ctx, points, opts);\r\n        canvas = null;\r\n    }\r\n    \r\n    function unhighlight (plot) {\r\n        var canvas = plot.plugins.lineRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            plot.series[i]._highlightedPoint = null;\r\n        }\r\n        plot.plugins.lineRenderer.highlightedSeriesIndex = null;\r\n        plot.target.trigger('jqplotDataUnhighlight');\r\n        canvas = null;\r\n    }\r\n    \r\n    \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt1 = jQuery.Event('jqplotDataMouseOver');\r\n            evt1.pageX = ev.pageX;\r\n            evt1.pageY = ev.pageY;\r\n            plot.target.trigger(evt1, ins);\r\n            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {\r\n        var idx = plot.plugins.lineRenderer.highlightedSeriesIndex;\r\n        if (idx != null && plot.series[idx].highlightMouseDown) {\r\n            unhighlight(plot);\r\n        }\r\n    }\r\n    \r\n    function handleClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt = jQuery.Event('jqplotDataClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var idx = plot.plugins.lineRenderer.highlightedSeriesIndex;\r\n            if (idx != null && plot.series[idx].highlightMouseDown) {\r\n                unhighlight(plot);\r\n            }\r\n            var evt = jQuery.Event('jqplotDataRightClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    \r\n    // class: $.jqplot.LinearAxisRenderer\r\n    // The default jqPlot axis renderer, creating a numeric axis.\r\n    $.jqplot.LinearAxisRenderer = function() {\r\n    };\r\n    \r\n    // called with scope of axis object.\r\n    $.jqplot.LinearAxisRenderer.prototype.init = function(options){\r\n        // prop: breakPoints\r\n        // EXPERIMENTAL!! Use at your own risk!\r\n        // Works only with linear axes and the default tick renderer.\r\n        // Array of [start, stop] points to create a broken axis.\r\n        // Broken axes have a \"jump\" in them, which is an immediate \r\n        // transition from a smaller value to a larger value.\r\n        // Currently, axis ticks MUST be manually assigned if using breakPoints\r\n        // by using the axis ticks array option.\r\n        this.breakPoints = null;\r\n        // prop: breakTickLabel\r\n        // Label to use at the axis break if breakPoints are specified.\r\n        this.breakTickLabel = \"&asymp;\";\r\n        // prop: drawBaseline\r\n        // True to draw the axis baseline.\r\n        this.drawBaseline = true;\r\n        // prop: baselineWidth\r\n        // width of the baseline in pixels.\r\n        this.baselineWidth = null;\r\n        // prop: baselineColor\r\n        // CSS color spec for the baseline.\r\n        this.baselineColor = null;\r\n        // prop: forceTickAt0\r\n        // This will ensure that there is always a tick mark at 0.\r\n        // If data range is strictly positive or negative,\r\n        // this will force 0 to be inside the axis bounds unless\r\n        // the appropriate axis pad (pad, padMin or padMax) is set\r\n        // to 0, then this will force an axis min or max value at 0.\r\n        // This has know effect when any of the following options\r\n        // are set:  autoscale, min, max, numberTicks or tickInterval.\r\n        this.forceTickAt0 = false;\r\n        // prop: forceTickAt100\r\n        // This will ensure that there is always a tick mark at 100.\r\n        // If data range is strictly above or below 100,\r\n        // this will force 100 to be inside the axis bounds unless\r\n        // the appropriate axis pad (pad, padMin or padMax) is set\r\n        // to 0, then this will force an axis min or max value at 100.\r\n        // This has know effect when any of the following options\r\n        // are set:  autoscale, min, max, numberTicks or tickInterval.\r\n        this.forceTickAt100 = false;\r\n        // prop: tickInset\r\n        // Controls the amount to inset the first and last ticks from \r\n        // the edges of the grid, in multiples of the tick interval.\r\n        // 0 is no inset, 0.5 is one half a tick interval, 1 is a full\r\n        // tick interval, etc.\r\n        this.tickInset = 0;\r\n        // prop: minorTicks\r\n        // Number of ticks to add between \"major\" ticks.\r\n        // Major ticks are ticks supplied by user or auto computed.\r\n        // Minor ticks cannot be created by user.\r\n        this.minorTicks = 0;\r\n        // prop: alignTicks\r\n        // true to align tick marks across opposed axes\r\n        // such as from the y2axis to yaxis.\r\n        this.alignTicks = false;\r\n        this._autoFormatString = '';\r\n        this._overrideFormatString = false;\r\n        this._scalefact = 1.0;\r\n        $.extend(true, this, options);\r\n        if (this.breakPoints) {\r\n            if (!$.isArray(this.breakPoints)) {\r\n                this.breakPoints = null;\r\n            }\r\n            else if (this.breakPoints.length < 2 || this.breakPoints[1] <= this.breakPoints[0]) {\r\n                this.breakPoints = null;\r\n            }\r\n        }\r\n        if (this.numberTicks != null && this.numberTicks < 2) {\r\n            this.numberTicks = 2;\r\n        }\r\n        this.resetDataBounds();\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.LinearAxisRenderer.prototype.draw = function(ctx, plot) {\r\n        if (this.show) {\r\n            // populate the axis label and value properties.\r\n            // createTicks is a method on the renderer, but\r\n            // call it within the scope of the axis.\r\n            this.renderer.createTicks.call(this, plot);\r\n            // fill a div with axes labels in the right direction.\r\n            // Need to pregenerate each axis to get its bounds and\r\n            // position it and the labels correctly on the plot.\r\n            var dim=0;\r\n            var temp;\r\n            // Added for theming.\r\n            if (this._elem) {\r\n                // Memory Leaks patch\r\n                //this._elem.empty();\r\n                this._elem.emptyForce();\r\n                this._elem = null;\r\n            }\r\n            \r\n            this._elem = $(document.createElement('div'));\r\n            this._elem.addClass('jqplot-axis jqplot-'+this.name);\r\n            this._elem.css('position', 'absolute');\r\n\r\n            \r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                this._elem.width(this._plotDimensions.width);\r\n            }\r\n            else {\r\n                this._elem.height(this._plotDimensions.height);\r\n            }\r\n            \r\n            // create a _label object.\r\n            this.labelOptions.axis = this.name;\r\n            this._label = new this.labelRenderer(this.labelOptions);\r\n            if (this._label.show) {\r\n                var elem = this._label.draw(ctx, plot);\r\n                elem.appendTo(this._elem);\r\n                elem = null;\r\n            }\r\n    \r\n            var t = this._ticks;\r\n            var tick;\r\n            for (var i=0; i<t.length; i++) {\r\n                tick = t[i];\r\n                if (tick.show && tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) {\r\n                    this._elem.append(tick.draw(ctx, plot));\r\n                }\r\n            }\r\n            tick = null;\r\n            t = null;\r\n        }\r\n        return this._elem;\r\n    };\r\n    \r\n    // called with scope of an axis\r\n    $.jqplot.LinearAxisRenderer.prototype.reset = function() {\r\n        this.min = this._options.min;\r\n        this.max = this._options.max;\r\n        this.tickInterval = this._options.tickInterval;\r\n        this.numberTicks = this._options.numberTicks;\r\n        this._autoFormatString = '';\r\n        if (this._overrideFormatString && this.tickOptions && this.tickOptions.formatString) {\r\n            this.tickOptions.formatString = '';\r\n        }\r\n\r\n        // this._ticks = this.__ticks;\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.LinearAxisRenderer.prototype.set = function() { \r\n        var dim = 0;\r\n        var temp;\r\n        var w = 0;\r\n        var h = 0;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        if (this.show) {\r\n            var t = this._ticks;\r\n            var tick;\r\n            for (var i=0; i<t.length; i++) {\r\n                tick = t[i];\r\n                if (!tick._breakTick && tick.show && tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) {\r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        temp = tick._elem.outerHeight(true);\r\n                    }\r\n                    else {\r\n                        temp = tick._elem.outerWidth(true);\r\n                    }\r\n                    if (temp > dim) {\r\n                        dim = temp;\r\n                    }\r\n                }\r\n            }\r\n            tick = null;\r\n            t = null;\r\n            \r\n            if (lshow) {\r\n                w = this._label._elem.outerWidth(true);\r\n                h = this._label._elem.outerHeight(true); \r\n            }\r\n            if (this.name == 'xaxis') {\r\n                dim = dim + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'});\r\n            }\r\n            else if (this.name == 'x2axis') {\r\n                dim = dim + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', top:'0px'});\r\n            }\r\n            else if (this.name == 'yaxis') {\r\n                dim = dim + w;\r\n                this._elem.css({'width':dim+'px', left:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n            else {\r\n                dim = dim + w;\r\n                this._elem.css({'width':dim+'px', right:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n        }  \r\n    };    \r\n    \r\n    // called with scope of axis\r\n    $.jqplot.LinearAxisRenderer.prototype.createTicks = function(plot) {\r\n        // we're are operating on an axis here\r\n        var ticks = this._ticks;\r\n        var userTicks = this.ticks;\r\n        var name = this.name;\r\n        // databounds were set on axis initialization.\r\n        var db = this._dataBounds;\r\n        var dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height;\r\n        var interval;\r\n        var min, max;\r\n        var pos1, pos2;\r\n        var tt, i;\r\n        // get a copy of user's settings for min/max.\r\n        var userMin = this.min;\r\n        var userMax = this.max;\r\n        var userNT = this.numberTicks;\r\n        var userTI = this.tickInterval;\r\n\r\n        var threshold = 30;\r\n        this._scalefact =  (Math.max(dim, threshold+1) - threshold)/300.0;\r\n        \r\n        // if we already have ticks, use them.\r\n        // ticks must be in order of increasing value.\r\n        \r\n        if (userTicks.length) {\r\n            // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed\r\n            for (i=0; i<userTicks.length; i++){\r\n                var ut = userTicks[i];\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                if ($.isArray(ut)) {\r\n                    t.value = ut[0];\r\n                    if (this.breakPoints) {\r\n                        if (ut[0] == this.breakPoints[0]) {\r\n                            t.label = this.breakTickLabel;\r\n                            t._breakTick = true;\r\n                            t.showGridline = false;\r\n                            t.showMark = false;\r\n                        }\r\n                        else if (ut[0] > this.breakPoints[0] && ut[0] <= this.breakPoints[1]) {\r\n                            t.show = false;\r\n                            t.showGridline = false;\r\n                            t.label = ut[1];\r\n                        }\r\n                        else {\r\n                            t.label = ut[1];\r\n                        }\r\n                    }\r\n                    else {\r\n                        t.label = ut[1];\r\n                    }\r\n                    t.setTick(ut[0], this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n\r\n                else if ($.isPlainObject(ut)) {\r\n                    $.extend(true, t, ut);\r\n                    t.axis = this.name;\r\n                    this._ticks.push(t);\r\n                }\r\n                \r\n                else {\r\n                    t.value = ut;\r\n                    if (this.breakPoints) {\r\n                        if (ut == this.breakPoints[0]) {\r\n                            t.label = this.breakTickLabel;\r\n                            t._breakTick = true;\r\n                            t.showGridline = false;\r\n                            t.showMark = false;\r\n                        }\r\n                        else if (ut > this.breakPoints[0] && ut <= this.breakPoints[1]) {\r\n                            t.show = false;\r\n                            t.showGridline = false;\r\n                        }\r\n                    }\r\n                    t.setTick(ut, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n            this.numberTicks = userTicks.length;\r\n            this.min = this._ticks[0].value;\r\n            this.max = this._ticks[this.numberTicks-1].value;\r\n            this.tickInterval = (this.max - this.min) / (this.numberTicks - 1);\r\n        }\r\n        \r\n        // we don't have any ticks yet, let's make some!\r\n        else {\r\n            if (name == 'xaxis' || name == 'x2axis') {\r\n                dim = this._plotDimensions.width;\r\n            }\r\n            else {\r\n                dim = this._plotDimensions.height;\r\n            }\r\n\r\n            var _numberTicks = this.numberTicks;\r\n\r\n            // if aligning this axis, use number of ticks from previous axis.\r\n            // Do I need to reset somehow if alignTicks is changed and then graph is replotted??\r\n            if (this.alignTicks) {\r\n                if (this.name === 'x2axis' && plot.axes.xaxis.show) {\r\n                    _numberTicks = plot.axes.xaxis.numberTicks;\r\n                }\r\n                else if (this.name.charAt(0) === 'y' && this.name !== 'yaxis' && this.name !== 'yMidAxis' && plot.axes.yaxis.show) {\r\n                    _numberTicks = plot.axes.yaxis.numberTicks;\r\n                }\r\n            }\r\n        \r\n            min = ((this.min != null) ? this.min : db.min);\r\n            max = ((this.max != null) ? this.max : db.max);\r\n\r\n            var range = max - min;\r\n            var rmin, rmax;\r\n            var temp;\r\n\r\n            if (this.tickOptions == null || !this.tickOptions.formatString) {\r\n                this._overrideFormatString = true;\r\n            }\r\n\r\n            // Doing complete autoscaling\r\n            if (this.min == null || this.max == null && this.tickInterval == null && !this.autoscale) {\r\n                // Check if user must have tick at 0 or 100 and ensure they are in range.\r\n                // The autoscaling algorithm will always place ticks at 0 and 100 if they are in range.\r\n                if (this.forceTickAt0) {\r\n                    if (min > 0) {\r\n                        min = 0;\r\n                    }\r\n                    if (max < 0) {\r\n                        max = 0;\r\n                    }\r\n                }\r\n\r\n                if (this.forceTickAt100) {\r\n                    if (min > 100) {\r\n                        min = 100;\r\n                    }\r\n                    if (max < 100) {\r\n                        max = 100;\r\n                    }\r\n                }\r\n\r\n                var keepMin = false,\r\n                    keepMax = false;\r\n\r\n                if (this.min != null) {\r\n                    keepMin = true;\r\n                }\r\n\r\n                else if (this.max != null) {\r\n                    keepMax = true;\r\n                }\r\n\r\n                // var threshold = 30;\r\n                // var tdim = Math.max(dim, threshold+1);\r\n                // this._scalefact =  (tdim-threshold)/300.0;\r\n                var ret = $.jqplot.LinearTickGenerator(min, max, this._scalefact, _numberTicks, keepMin, keepMax); \r\n                // calculate a padded max and min, points should be less than these\r\n                // so that they aren't too close to the edges of the plot.\r\n                // User can adjust how much padding is allowed with pad, padMin and PadMax options. \r\n                // If min or max is set, don't pad that end of axis.\r\n                var tumin = (this.min != null) ? min : min + range*(this.padMin - 1);\r\n                var tumax = (this.max != null) ? max : max - range*(this.padMax - 1);\r\n\r\n                // if they're equal, we shouldn't have to do anything, right?\r\n                // if (min <=tumin || max >= tumax) {\r\n                if (min <tumin || max > tumax) {\r\n                    tumin = (this.min != null) ? min : min - range*(this.padMin - 1);\r\n                    tumax = (this.max != null) ? max : max + range*(this.padMax - 1);\r\n                    ret = $.jqplot.LinearTickGenerator(tumin, tumax, this._scalefact, _numberTicks, keepMin, keepMax);\r\n                }\r\n\r\n                this.min = ret[0];\r\n                this.max = ret[1];\r\n                // if numberTicks specified, it should return the same.\r\n                this.numberTicks = ret[2];\r\n                this._autoFormatString = ret[3];\r\n                this.tickInterval = ret[4];\r\n            }\r\n\r\n            // User has specified some axis scale related option, can use auto algorithm\r\n            else {\r\n                \r\n                // if min and max are same, space them out a bit\r\n                if (min == max) {\r\n                    var adj = 0.05;\r\n                    if (min > 0) {\r\n                        adj = Math.max(Math.log(min)/Math.LN10, 0.05);\r\n                    }\r\n                    min -= adj;\r\n                    max += adj;\r\n                }\r\n                \r\n                // autoscale.  Can't autoscale if min or max is supplied.\r\n                // Will use numberTicks and tickInterval if supplied.  Ticks\r\n                // across multiple axes may not line up depending on how\r\n                // bars are to be plotted.\r\n                if (this.autoscale && this.min == null && this.max == null) {\r\n                    var rrange, ti, margin;\r\n                    var forceMinZero = false;\r\n                    var forceZeroLine = false;\r\n                    var intervals = {min:null, max:null, average:null, stddev:null};\r\n                    // if any series are bars, or if any are fill to zero, and if this\r\n                    // is the axis to fill toward, check to see if we can start axis at zero.\r\n                    for (var i=0; i<this._series.length; i++) {\r\n                        var s = this._series[i];\r\n                        var faname = (s.fillAxis == 'x') ? s._xaxis.name : s._yaxis.name;\r\n                        // check to see if this is the fill axis\r\n                        if (this.name == faname) {\r\n                            var vals = s._plotValues[s.fillAxis];\r\n                            var vmin = vals[0];\r\n                            var vmax = vals[0];\r\n                            for (var j=1; j<vals.length; j++) {\r\n                                if (vals[j] < vmin) {\r\n                                    vmin = vals[j];\r\n                                }\r\n                                else if (vals[j] > vmax) {\r\n                                    vmax = vals[j];\r\n                                }\r\n                            }\r\n                            var dp = (vmax - vmin) / vmax;\r\n                            // is this sries a bar?\r\n                            if (s.renderer.constructor == $.jqplot.BarRenderer) {\r\n                                // if no negative values and could also check range.\r\n                                if (vmin >= 0 && (s.fillToZero || dp > 0.1)) {\r\n                                    forceMinZero = true;\r\n                                }\r\n                                else {\r\n                                    forceMinZero = false;\r\n                                    if (s.fill && s.fillToZero && vmin < 0 && vmax > 0) {\r\n                                        forceZeroLine = true;\r\n                                    }\r\n                                    else {\r\n                                        forceZeroLine = false;\r\n                                    }\r\n                                }\r\n                            }\r\n                            \r\n                            // if not a bar and filling, use appropriate method.\r\n                            else if (s.fill) {\r\n                                if (vmin >= 0 && (s.fillToZero || dp > 0.1)) {\r\n                                    forceMinZero = true;\r\n                                }\r\n                                else if (vmin < 0 && vmax > 0 && s.fillToZero) {\r\n                                    forceMinZero = false;\r\n                                    forceZeroLine = true;\r\n                                }\r\n                                else {\r\n                                    forceMinZero = false;\r\n                                    forceZeroLine = false;\r\n                                }\r\n                            }\r\n                            \r\n                            // if not a bar and not filling, only change existing state\r\n                            // if it doesn't make sense\r\n                            else if (vmin < 0) {\r\n                                forceMinZero = false;\r\n                            }\r\n                        }\r\n                    }\r\n                    \r\n                    // check if we need make axis min at 0.\r\n                    if (forceMinZero) {\r\n                        // compute number of ticks\r\n                        this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing);\r\n                        this.min = 0;\r\n                        userMin = 0;\r\n                        // what order is this range?\r\n                        // what tick interval does that give us?\r\n                        ti = max/(this.numberTicks-1);\r\n                        temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10)));\r\n                        if (ti/temp == parseInt(ti/temp, 10)) {\r\n                            ti += temp;\r\n                        }\r\n                        this.tickInterval = Math.ceil(ti/temp) * temp;\r\n                        this.max = this.tickInterval * (this.numberTicks - 1);\r\n                    }\r\n                    \r\n                    // check if we need to make sure there is a tick at 0.\r\n                    else if (forceZeroLine) {\r\n                        // compute number of ticks\r\n                        this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing);\r\n                        var ntmin = Math.ceil(Math.abs(min)/range*(this.numberTicks-1));\r\n                        var ntmax = this.numberTicks - 1  - ntmin;\r\n                        ti = Math.max(Math.abs(min/ntmin), Math.abs(max/ntmax));\r\n                        temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10)));\r\n                        this.tickInterval = Math.ceil(ti/temp) * temp;\r\n                        this.max = this.tickInterval * ntmax;\r\n                        this.min = -this.tickInterval * ntmin;\r\n                    }\r\n                    \r\n                    // if nothing else, do autoscaling which will try to line up ticks across axes.\r\n                    else {  \r\n                        if (this.numberTicks == null){\r\n                            if (this.tickInterval) {\r\n                                this.numberTicks = 3 + Math.ceil(range / this.tickInterval);\r\n                            }\r\n                            else {\r\n                                this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing);\r\n                            }\r\n                        }\r\n                \r\n                        if (this.tickInterval == null) {\r\n                            // get a tick interval\r\n                            ti = range/(this.numberTicks - 1);\r\n\r\n                            if (ti < 1) {\r\n                                temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10)));\r\n                            }\r\n                            else {\r\n                                temp = 1;\r\n                            }\r\n                            this.tickInterval = Math.ceil(ti*temp*this.pad)/temp;\r\n                        }\r\n                        else {\r\n                            temp = 1 / this.tickInterval;\r\n                        }\r\n                        \r\n                        // try to compute a nicer, more even tick interval\r\n                        // temp = Math.pow(10, Math.floor(Math.log(ti)/Math.LN10));\r\n                        // this.tickInterval = Math.ceil(ti/temp) * temp;\r\n                        rrange = this.tickInterval * (this.numberTicks - 1);\r\n                        margin = (rrange - range)/2;\r\n           \r\n                        if (this.min == null) {\r\n                            this.min = Math.floor(temp*(min-margin))/temp;\r\n                        }\r\n                        if (this.max == null) {\r\n                            this.max = this.min + rrange;\r\n                        }\r\n                    }\r\n\r\n                    // Compute a somewhat decent format string if it is needed.\r\n                    // get precision of interval and determine a format string.\r\n                    var sf = $.jqplot.getSignificantFigures(this.tickInterval);\r\n\r\n                    var fstr;\r\n\r\n                    // if we have only a whole number, use integer formatting\r\n                    if (sf.digitsLeft >= sf.significantDigits) {\r\n                        fstr = '%d';\r\n                    }\r\n\r\n                    else {\r\n                        var temp = Math.max(0, 5 - sf.digitsLeft);\r\n                        temp = Math.min(temp, sf.digitsRight);\r\n                        fstr = '%.'+ temp + 'f';\r\n                    }\r\n\r\n                    this._autoFormatString = fstr;\r\n                }\r\n                \r\n                // Use the default algorithm which pads each axis to make the chart\r\n                // centered nicely on the grid.\r\n                else {\r\n\r\n                    rmin = (this.min != null) ? this.min : min - range*(this.padMin - 1);\r\n                    rmax = (this.max != null) ? this.max : max + range*(this.padMax - 1);\r\n                    range = rmax - rmin;\r\n        \r\n                    if (this.numberTicks == null){\r\n                        // if tickInterval is specified by user, we will ignore computed maximum.\r\n                        // max will be equal or greater to fit even # of ticks.\r\n                        if (this.tickInterval != null) {\r\n                            this.numberTicks = Math.ceil((rmax - rmin)/this.tickInterval)+1;\r\n                        }\r\n                        else if (dim > 100) {\r\n                            this.numberTicks = parseInt(3+(dim-100)/75, 10);\r\n                        }\r\n                        else {\r\n                            this.numberTicks = 2;\r\n                        }\r\n                    }\r\n                \r\n                    if (this.tickInterval == null) {\r\n                        this.tickInterval = range / (this.numberTicks-1);\r\n                    }\r\n                    \r\n                    if (this.max == null) {\r\n                        rmax = rmin + this.tickInterval*(this.numberTicks - 1);\r\n                    }        \r\n                    if (this.min == null) {\r\n                        rmin = rmax - this.tickInterval*(this.numberTicks - 1);\r\n                    }\r\n\r\n                    // get precision of interval and determine a format string.\r\n                    var sf = $.jqplot.getSignificantFigures(this.tickInterval);\r\n\r\n                    var fstr;\r\n\r\n                    // if we have only a whole number, use integer formatting\r\n                    if (sf.digitsLeft >= sf.significantDigits) {\r\n                        fstr = '%d';\r\n                    }\r\n\r\n                    else {\r\n                        var temp = Math.max(0, 5 - sf.digitsLeft);\r\n                        temp = Math.min(temp, sf.digitsRight);\r\n                        fstr = '%.'+ temp + 'f';\r\n                    }\r\n\r\n\r\n                    this._autoFormatString = fstr;\r\n\r\n                    this.min = rmin;\r\n                    this.max = rmax;\r\n                }\r\n                \r\n                if (this.renderer.constructor == $.jqplot.LinearAxisRenderer && this._autoFormatString == '') {\r\n                    // fix for misleading tick display with small range and low precision.\r\n                    range = this.max - this.min;\r\n                    // figure out precision\r\n                    var temptick = new this.tickRenderer(this.tickOptions);\r\n                    // use the tick formatString or, the default.\r\n                    var fs = temptick.formatString || $.jqplot.config.defaultTickFormatString; \r\n                    var fs = fs.match($.jqplot.sprintf.regex)[0];\r\n                    var precision = 0;\r\n                    if (fs) {\r\n                        if (fs.search(/[fFeEgGpP]/) > -1) {\r\n                            var m = fs.match(/\\%\\.(\\d{0,})?[eEfFgGpP]/);\r\n                            if (m) {\r\n                                precision = parseInt(m[1], 10);\r\n                            }\r\n                            else {\r\n                                precision = 6;\r\n                            }\r\n                        }\r\n                        else if (fs.search(/[di]/) > -1) {\r\n                            precision = 0;\r\n                        }\r\n                        // fact will be <= 1;\r\n                        var fact = Math.pow(10, -precision);\r\n                        if (this.tickInterval < fact) {\r\n                            // need to correct underrange\r\n                            if (userNT == null && userTI == null) {\r\n                                this.tickInterval = fact;\r\n                                if (userMax == null && userMin == null) {\r\n                                    // this.min = Math.floor((this._dataBounds.min - this.tickInterval)/fact) * fact;\r\n                                    this.min = Math.floor(this._dataBounds.min/fact) * fact;\r\n                                    if (this.min == this._dataBounds.min) {\r\n                                        this.min = this._dataBounds.min - this.tickInterval;\r\n                                    }\r\n                                    // this.max = Math.ceil((this._dataBounds.max + this.tickInterval)/fact) * fact;\r\n                                    this.max = Math.ceil(this._dataBounds.max/fact) * fact;\r\n                                    if (this.max == this._dataBounds.max) {\r\n                                        this.max = this._dataBounds.max + this.tickInterval;\r\n                                    }\r\n                                    var n = (this.max - this.min)/this.tickInterval;\r\n                                    n = n.toFixed(11);\r\n                                    n = Math.ceil(n);\r\n                                    this.numberTicks = n + 1;\r\n                                }\r\n                                else if (userMax == null) {\r\n                                    // add one tick for top of range.\r\n                                    var n = (this._dataBounds.max - this.min) / this.tickInterval;\r\n                                    n = n.toFixed(11);\r\n                                    this.numberTicks = Math.ceil(n) + 2;\r\n                                    this.max = this.min + this.tickInterval * (this.numberTicks-1);\r\n                                }\r\n                                else if (userMin == null) {\r\n                                    // add one tick for bottom of range.\r\n                                    var n = (this.max - this._dataBounds.min) / this.tickInterval;\r\n                                    n = n.toFixed(11);\r\n                                    this.numberTicks = Math.ceil(n) + 2;\r\n                                    this.min = this.max - this.tickInterval * (this.numberTicks-1);\r\n                                }\r\n                                else {\r\n                                    // calculate a number of ticks so max is within axis scale\r\n                                    this.numberTicks = Math.ceil((userMax - userMin)/this.tickInterval) + 1;\r\n                                    // if user's min and max don't fit evenly in ticks, adjust.\r\n                                    // This takes care of cases such as user min set to 0, max set to 3.5 but tick\r\n                                    // format string set to %d (integer ticks)\r\n                                    this.min =  Math.floor(userMin*Math.pow(10, precision))/Math.pow(10, precision);\r\n                                    this.max =  Math.ceil(userMax*Math.pow(10, precision))/Math.pow(10, precision);\r\n                                    // this.max = this.min + this.tickInterval*(this.numberTicks-1);\r\n                                    this.numberTicks = Math.ceil((this.max - this.min)/this.tickInterval) + 1;\r\n                                }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                \r\n            }\r\n            \r\n            if (this._overrideFormatString && this._autoFormatString != '') {\r\n                this.tickOptions = this.tickOptions || {};\r\n                this.tickOptions.formatString = this._autoFormatString;\r\n            }\r\n\r\n            var t, to;\r\n            for (var i=0; i<this.numberTicks; i++){\r\n                tt = this.min + i * this.tickInterval;\r\n                t = new this.tickRenderer(this.tickOptions);\r\n                // var t = new $.jqplot.AxisTickRenderer(this.tickOptions);\r\n\r\n                t.setTick(tt, this.name);\r\n                this._ticks.push(t);\r\n\r\n                if (i < this.numberTicks - 1) {\r\n                    for (var j=0; j<this.minorTicks; j++) {\r\n                        tt += this.tickInterval/(this.minorTicks+1);\r\n                        to = $.extend(true, {}, this.tickOptions, {name:this.name, value:tt, label:'', isMinorTick:true});\r\n                        t = new this.tickRenderer(to);\r\n                        this._ticks.push(t);\r\n                    }\r\n                }\r\n                t = null;\r\n            }\r\n        }\r\n\r\n        if (this.tickInset) {\r\n            this.min = this.min - this.tickInset * this.tickInterval;\r\n            this.max = this.max + this.tickInset * this.tickInterval;\r\n        }\r\n\r\n        ticks = null;\r\n    };\r\n    \r\n    // Used to reset just the values of the ticks and then repack, which will\r\n    // recalculate the positioning functions.  It is assuemd that the \r\n    // number of ticks is the same and the values of the new array are at the\r\n    // proper interval.\r\n    // This method needs to be called with the scope of an axis object, like:\r\n    //\r\n    // > plot.axes.yaxis.renderer.resetTickValues.call(plot.axes.yaxis, yarr);\r\n    //\r\n    $.jqplot.LinearAxisRenderer.prototype.resetTickValues = function(opts) {\r\n        if ($.isArray(opts) && opts.length == this._ticks.length) {\r\n            var t;\r\n            for (var i=0; i<opts.length; i++) {\r\n                t = this._ticks[i];\r\n                t.value = opts[i];\r\n                t.label = t.formatter(t.formatString, opts[i]);\r\n                t.label = t.prefix + t.label;\r\n                t._elem.html(t.label);\r\n            }\r\n            t = null;\r\n            this.min = $.jqplot.arrayMin(opts);\r\n            this.max = $.jqplot.arrayMax(opts);\r\n            this.pack();\r\n        }\r\n        // Not implemented yet.\r\n        // else if ($.isPlainObject(opts)) {\r\n        // \r\n        // }\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.LinearAxisRenderer.prototype.pack = function(pos, offsets) {\r\n        // Add defaults for repacking from resetTickValues function.\r\n        pos = pos || {};\r\n        offsets = offsets || this._offsets;\r\n        \r\n        var ticks = this._ticks;\r\n        var max = this.max;\r\n        var min = this.min;\r\n        var offmax = offsets.max;\r\n        var offmin = offsets.min;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        \r\n        for (var p in pos) {\r\n            this._elem.css(p, pos[p]);\r\n        }\r\n        \r\n        this._offsets = offsets;\r\n        // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left.\r\n        var pixellength = offmax - offmin;\r\n        var unitlength = max - min;\r\n        \r\n        // point to unit and unit to point conversions references to Plot DOM element top left corner.\r\n        if (this.breakPoints) {\r\n            unitlength = unitlength - this.breakPoints[1] + this.breakPoints[0];\r\n            \r\n            this.p2u = function(p){\r\n                return (p - offmin) * unitlength / pixellength + min;\r\n            };\r\n        \r\n            this.u2p = function(u){\r\n                if (u > this.breakPoints[0] && u < this.breakPoints[1]){\r\n                    u = this.breakPoints[0];\r\n                }\r\n                if (u <= this.breakPoints[0]) {\r\n                    return (u - min) * pixellength / unitlength + offmin;\r\n                }\r\n                else {\r\n                    return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength + offmin;\r\n                }\r\n            };\r\n                \r\n            if (this.name.charAt(0) == 'x'){\r\n                this.series_u2p = function(u){\r\n                    if (u > this.breakPoints[0] && u < this.breakPoints[1]){\r\n                        u = this.breakPoints[0];\r\n                    }\r\n                    if (u <= this.breakPoints[0]) {\r\n                        return (u - min) * pixellength / unitlength;\r\n                    }\r\n                    else {\r\n                        return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength;\r\n                    }\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + min;\r\n                };\r\n            }\r\n        \r\n            else {\r\n                this.series_u2p = function(u){\r\n                    if (u > this.breakPoints[0] && u < this.breakPoints[1]){\r\n                        u = this.breakPoints[0];\r\n                    }\r\n                    if (u >= this.breakPoints[1]) {\r\n                        return (u - max) * pixellength / unitlength;\r\n                    }\r\n                    else {\r\n                        return (u + this.breakPoints[1] - this.breakPoints[0] - max) * pixellength / unitlength;\r\n                    }\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + max;\r\n                };\r\n            }\r\n        }\r\n        else {\r\n            this.p2u = function(p){\r\n                return (p - offmin) * unitlength / pixellength + min;\r\n            };\r\n        \r\n            this.u2p = function(u){\r\n                return (u - min) * pixellength / unitlength + offmin;\r\n            };\r\n                \r\n            if (this.name == 'xaxis' || this.name == 'x2axis'){\r\n                this.series_u2p = function(u){\r\n                    return (u - min) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + min;\r\n                };\r\n            }\r\n        \r\n            else {\r\n                this.series_u2p = function(u){\r\n                    return (u - max) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + max;\r\n                };\r\n            }\r\n        }\r\n        \r\n        if (this.show) {\r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {\r\n                        var shim;\r\n                        \r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'xaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    // position at start\r\n                                    else {\r\n                                        shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'end':\r\n                                    shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'start':\r\n                                    shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'middle':\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getWidth()/2;\r\n                        }\r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('left', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                if (lshow) {\r\n                    var w = this._label._elem.outerWidth(true);\r\n                    this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px');\r\n                    if (this.name == 'xaxis') {\r\n                        this._label._elem.css('bottom', '0px');\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('top', '0px');\r\n                    }\r\n                    this._label.pack();\r\n                }\r\n            }\r\n            else {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {                        \r\n                        var shim;\r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'yaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                case 'end':\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'start':\r\n                                    if (t.angle > 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'middle':\r\n                                    // if (t.angle > 0) {\r\n                                    //     shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    // else {\r\n                                    //     shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getHeight()/2;\r\n                        }\r\n                        \r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('top', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                if (lshow) {\r\n                    var h = this._label._elem.outerHeight(true);\r\n                    this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px');\r\n                    if (this.name == 'yaxis') {\r\n                        this._label._elem.css('left', '0px');\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('right', '0px');\r\n                    }   \r\n                    this._label.pack();\r\n                }\r\n            }\r\n        }\r\n\r\n        ticks = null;\r\n    };\r\n\r\n\r\n    /**\r\n    * The following code was generaously given to me a while back by Scott Prahl.\r\n    * He did a good job at computing axes min, max and number of ticks for the \r\n    * case where the user has not set any scale related parameters (tickInterval,\r\n    * numberTicks, min or max).  I had ignored this use case for a long time,\r\n    * focusing on the more difficult case where user has set some option controlling\r\n    * tick generation.  Anyway, about time I got this into jqPlot.\r\n    * Thanks Scott!!\r\n    */\r\n    \r\n    /**\r\n    * Copyright (c) 2010 Scott Prahl\r\n    * The next three routines are currently available for use in all personal \r\n    * or commercial projects under both the MIT and GPL version 2.0 licenses. \r\n    * This means that you can choose the license that best suits your project \r\n    * and use it accordingly. \r\n    */\r\n\r\n    // A good format string depends on the interval. If the interval is greater \r\n    // than 1 then there is no need to show any decimal digits. If it is < 1.0, then\r\n    // use the magnitude of the interval to determine the number of digits to show.\r\n    function bestFormatString (interval)\r\n    {\r\n        var fstr;\r\n        interval = Math.abs(interval);\r\n        if (interval >= 10) {\r\n            fstr = '%d';\r\n        }\r\n\r\n        else if (interval > 1) {\r\n            if (interval === parseInt(interval, 10)) {\r\n                fstr = '%d';\r\n            }\r\n            else {\r\n                fstr = '%.1f';\r\n            }\r\n        }\r\n\r\n        else {\r\n            var expv = -Math.floor(Math.log(interval)/Math.LN10);\r\n            fstr = '%.' + expv + 'f';\r\n        }\r\n        \r\n        return fstr; \r\n    }\r\n\r\n    var _factors = [0.1, 0.2, 0.3, 0.4, 0.5, 0.8, 1, 2, 3, 4, 5];\r\n\r\n    var _getLowerFactor = function(f) {\r\n        var i = _factors.indexOf(f);\r\n        if (i > 0) {\r\n            return _factors[i-1];\r\n        }\r\n        else {\r\n            return _factors[_factors.length - 1] / 100;\r\n        }\r\n    };\r\n\r\n    var _getHigherFactor = function(f) {\r\n        var i = _factors.indexOf(f);\r\n        if (i < _factors.length-1) {\r\n            return _factors[i+1];\r\n        }\r\n        else {\r\n            return _factors[0] * 100;\r\n        }\r\n    };\r\n\r\n    // Given a fixed minimum and maximum and a target number ot ticks\r\n    // figure out the best interval and \r\n    // return min, max, number ticks, format string and tick interval\r\n    function bestConstrainedInterval(min, max, nttarget) {\r\n        // run through possible number to ticks and see which interval is best\r\n        var low = Math.floor(nttarget/2);\r\n        var hi = Math.ceil(nttarget*1.5);\r\n        var badness = Number.MAX_VALUE;\r\n        var r = (max - min);\r\n        var temp;\r\n        var sd;\r\n        var bestNT;\r\n        var gsf = $.jqplot.getSignificantFigures;\r\n        var fsd;\r\n        var fs;\r\n        var currentNT;\r\n        var bestPrec;\r\n\r\n        for (var i=0, l=hi-low+1; i<l; i++) {\r\n            currentNT = low + i;\r\n            temp = r/(currentNT-1);\r\n            sd = gsf(temp);\r\n\r\n            temp = Math.abs(nttarget - currentNT) + sd.digitsRight;\r\n            if (temp < badness) {\r\n                badness = temp;\r\n                bestNT = currentNT;\r\n                bestPrec = sd.digitsRight;\r\n            }\r\n            else if (temp === badness) {\r\n                // let nicer ticks trump number ot ticks\r\n                if (sd.digitsRight < bestPrec) {\r\n                    bestNT = currentNT;\r\n                    bestPrec = sd.digitsRight;\r\n                }\r\n            }\r\n\r\n        }\r\n\r\n        fsd = Math.max(bestPrec, Math.max(gsf(min).digitsRight, gsf(max).digitsRight));\r\n        if (fsd === 0) {\r\n            fs = '%d';\r\n        }\r\n        else {\r\n            fs = '%.' + fsd + 'f';\r\n        }\r\n        temp = r / (bestNT - 1);\r\n        // min, max, number ticks, format string, tick interval\r\n        return [min, max, bestNT, fs, temp];\r\n    }\r\n\r\n    // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n\r\n    // it is based soley on the range and number of ticks.  So if user specifies\r\n    // number of ticks, use this.\r\n    function bestInterval(range, numberTicks) {\r\n        numberTicks = numberTicks || 7;\r\n        var minimum = range / (numberTicks - 1);\r\n        var magnitude = Math.pow(10, Math.floor(Math.log(minimum) / Math.LN10));\r\n        var residual = minimum / magnitude;\r\n        var interval;\r\n        // \"nicest\" ranges are 1, 2, 5 or powers of these.\r\n        // for magnitudes below 1, only allow these. \r\n        if (magnitude < 1) {\r\n            if (residual > 5) {\r\n                interval = 10 * magnitude;\r\n            }\r\n            else if (residual > 2) {\r\n                interval = 5 * magnitude;\r\n            }\r\n            else if (residual > 1) {\r\n                interval = 2 * magnitude;\r\n            }\r\n            else {\r\n                interval = magnitude;\r\n            }\r\n        }\r\n        // for large ranges (whole integers), allow intervals like 3, 4 or powers of these.\r\n        // this helps a lot with poor choices for number of ticks. \r\n        else {\r\n            if (residual > 5) {\r\n                interval = 10 * magnitude;\r\n            }\r\n            else if (residual > 4) {\r\n                interval = 5 * magnitude;\r\n            }\r\n            else if (residual > 3) {\r\n                interval = 4 * magnitude;\r\n            }\r\n            else if (residual > 2) {\r\n                interval = 3 * magnitude;\r\n            }\r\n            else if (residual > 1) {\r\n                interval = 2 * magnitude;\r\n            }\r\n            else {\r\n                interval = magnitude;\r\n            }\r\n        }\r\n\r\n        return interval;\r\n    }\r\n\r\n    // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n\r\n    // it is based soley on the range of data, number of ticks must be computed later.\r\n    function bestLinearInterval(range, scalefact) {\r\n        scalefact = scalefact || 1;\r\n        var expv = Math.floor(Math.log(range)/Math.LN10);\r\n        var magnitude = Math.pow(10, expv);\r\n        // 0 < f < 10\r\n        var f = range / magnitude;\r\n        var fact;\r\n        // for large plots, scalefact will decrease f and increase number of ticks.\r\n        // for small plots, scalefact will increase f and decrease number of ticks.\r\n        f = f/scalefact;\r\n\r\n        // for large plots, smaller interval, more ticks.\r\n        if (f<=0.38) {\r\n            fact = 0.1;\r\n        }\r\n        else if (f<=1.6) {\r\n            fact = 0.2;\r\n        }\r\n        else if (f<=4.0) {\r\n            fact = 0.5;\r\n        }\r\n        else if (f<=8.0) {\r\n            fact = 1.0;\r\n        }\r\n        // for very small plots, larger interval, less ticks in number ticks\r\n        else if (f<=16.0) {\r\n            fact = 2;\r\n        }\r\n        else {\r\n            fact = 5;\r\n        } \r\n\r\n        return fact*magnitude; \r\n    }\r\n\r\n    function bestLinearComponents(range, scalefact) {\r\n        var expv = Math.floor(Math.log(range)/Math.LN10);\r\n        var magnitude = Math.pow(10, expv);\r\n        // 0 < f < 10\r\n        var f = range / magnitude;\r\n        var interval;\r\n        var fact;\r\n        // for large plots, scalefact will decrease f and increase number of ticks.\r\n        // for small plots, scalefact will increase f and decrease number of ticks.\r\n        f = f/scalefact;\r\n\r\n        // for large plots, smaller interval, more ticks.\r\n        if (f<=0.38) {\r\n            fact = 0.1;\r\n        }\r\n        else if (f<=1.6) {\r\n            fact = 0.2;\r\n        }\r\n        else if (f<=4.0) {\r\n            fact = 0.5;\r\n        }\r\n        else if (f<=8.0) {\r\n            fact = 1.0;\r\n        }\r\n        // for very small plots, larger interval, less ticks in number ticks\r\n        else if (f<=16.0) {\r\n            fact = 2;\r\n        }\r\n        // else if (f<=20.0) {\r\n        //     fact = 3;\r\n        // }\r\n        // else if (f<=24.0) {\r\n        //     fact = 4;\r\n        // }\r\n        else {\r\n            fact = 5;\r\n        } \r\n\r\n        interval = fact * magnitude;\r\n\r\n        return [interval, fact, magnitude];\r\n    }\r\n\r\n    // Given the min and max for a dataset, return suitable endpoints\r\n    // for the graphing, a good number for the number of ticks, and a\r\n    // format string so that extraneous digits are not displayed.\r\n    // returned is an array containing [min, max, nTicks, format]\r\n    $.jqplot.LinearTickGenerator = function(axis_min, axis_max, scalefact, numberTicks, keepMin, keepMax) {\r\n        // Set to preserve EITHER min OR max.\r\n        // If min is preserved, max must be free.\r\n        keepMin = (keepMin === null) ? false : keepMin;\r\n        keepMax = (keepMax === null || keepMin) ? false : keepMax;\r\n        // if endpoints are equal try to include zero otherwise include one\r\n        if (axis_min === axis_max) {\r\n            axis_max = (axis_max) ? 0 : 1;\r\n        }\r\n\r\n        scalefact = scalefact || 1.0;\r\n\r\n        // make sure range is positive\r\n        if (axis_max < axis_min) {\r\n            var a = axis_max;\r\n            axis_max = axis_min;\r\n            axis_min = a;\r\n        }\r\n\r\n        var r = [];\r\n        var ss = bestLinearInterval(axis_max - axis_min, scalefact);\r\n\r\n        var gsf = $.jqplot.getSignificantFigures;\r\n        \r\n        if (numberTicks == null) {\r\n\r\n            // Figure out the axis min, max and number of ticks\r\n            // the min and max will be some multiple of the tick interval,\r\n            // 1*10^n, 2*10^n or 5*10^n.  This gaurantees that, if the\r\n            // axis min is negative, 0 will be a tick.\r\n            if (!keepMin && !keepMax) {\r\n                r[0] = Math.floor(axis_min / ss) * ss;  // min\r\n                r[1] = Math.ceil(axis_max / ss) * ss;   // max\r\n                r[2] = Math.round((r[1]-r[0])/ss+1.0);  // number of ticks\r\n                r[3] = bestFormatString(ss);            // format string\r\n                r[4] = ss;                              // tick Interval\r\n            }\r\n\r\n            else if (keepMin) {\r\n                r[0] = axis_min;                                        // min\r\n                r[2] = Math.ceil((axis_max - axis_min) / ss + 1.0);     // number of ticks\r\n                r[1] = axis_min + (r[2] - 1) * ss;                      // max\r\n                var digitsMin = gsf(axis_min).digitsRight;\r\n                var digitsSS = gsf(ss).digitsRight;\r\n                if (digitsMin < digitsSS) {\r\n                    r[3] = bestFormatString(ss);                        // format string\r\n                }\r\n                else {\r\n                    r[3] = '%.' + digitsMin + 'f';\r\n                }\r\n                r[4] = ss;                                              // tick Interval\r\n            }\r\n\r\n            else if (keepMax) {\r\n                r[1] = axis_max;                                        // max\r\n                r[2] = Math.ceil((axis_max - axis_min) / ss + 1.0);     // number of ticks\r\n                r[0] = axis_max - (r[2] - 1) * ss;                      // min\r\n                var digitsMax = gsf(axis_max).digitsRight;\r\n                var digitsSS = gsf(ss).digitsRight;\r\n                if (digitsMax < digitsSS) {\r\n                    r[3] = bestFormatString(ss);                        // format string\r\n                }\r\n                else {\r\n                    r[3] = '%.' + digitsMax + 'f';\r\n                }\r\n                r[4] = ss;                                              // tick Interval\r\n            }\r\n        }\r\n\r\n        else {\r\n            var tempr = [];\r\n\r\n            // Figure out the axis min, max and number of ticks\r\n            // the min and max will be some multiple of the tick interval,\r\n            // 1*10^n, 2*10^n or 5*10^n.  This gaurantees that, if the\r\n            // axis min is negative, 0 will be a tick.\r\n            tempr[0] = Math.floor(axis_min / ss) * ss;  // min\r\n            tempr[1] = Math.ceil(axis_max / ss) * ss;   // max\r\n            tempr[2] = Math.round((tempr[1]-tempr[0])/ss+1.0);    // number of ticks\r\n            tempr[3] = bestFormatString(ss);            // format string\r\n            tempr[4] = ss;                              // tick Interval\r\n\r\n            // first, see if we happen to get the right number of ticks\r\n            if (tempr[2] === numberTicks) {\r\n                r = tempr;\r\n            }\r\n\r\n            else {\r\n\r\n                var newti = bestInterval(tempr[1] - tempr[0], numberTicks);\r\n\r\n                r[0] = tempr[0];                        // min\r\n                r[2] = numberTicks;                     // number of ticks\r\n                r[4] = newti;                           // tick interval\r\n                r[3] = bestFormatString(newti);         // format string\r\n                r[1] = r[0] + (r[2] - 1) * r[4];        // max\r\n            }\r\n        }\r\n\r\n        return r;\r\n    };\r\n\r\n    $.jqplot.LinearTickGenerator.bestLinearInterval = bestLinearInterval;\r\n    $.jqplot.LinearTickGenerator.bestInterval = bestInterval;\r\n    $.jqplot.LinearTickGenerator.bestLinearComponents = bestLinearComponents;\r\n    $.jqplot.LinearTickGenerator.bestConstrainedInterval = bestConstrainedInterval;\r\n\r\n\r\n    // class: $.jqplot.MarkerRenderer\r\n    // The default jqPlot marker renderer, rendering the points on the line.\r\n    $.jqplot.MarkerRenderer = function(options){\r\n        // Group: Properties\r\n        \r\n        // prop: show\r\n        // whether or not to show the marker.\r\n        this.show = true;\r\n        // prop: style\r\n        // One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare\r\n        this.style = 'filledCircle';\r\n        // prop: lineWidth\r\n        // size of the line for non-filled markers.\r\n        this.lineWidth = 2;\r\n        // prop: size\r\n        // Size of the marker (diameter or circle, length of edge of square, etc.)\r\n        this.size = 9.0;\r\n        // prop: color\r\n        // color of marker.  Will be set to color of series by default on init.\r\n        this.color = '#666666';\r\n        // prop: shadow\r\n        // whether or not to draw a shadow on the line\r\n        this.shadow = true;\r\n        // prop: shadowAngle\r\n        // Shadow angle in degrees\r\n        this.shadowAngle = 45;\r\n        // prop: shadowOffset\r\n        // Shadow offset from line in pixels\r\n        this.shadowOffset = 1;\r\n        // prop: shadowDepth\r\n        // Number of times shadow is stroked, each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 3;\r\n        // prop: shadowAlpha\r\n        // Alpha channel transparency of shadow.  0 = transparent.\r\n        this.shadowAlpha = '0.07';\r\n        // prop: shadowRenderer\r\n        // Renderer that will draws the shadows on the marker.\r\n        this.shadowRenderer = new $.jqplot.ShadowRenderer();\r\n        // prop: shapeRenderer\r\n        // Renderer that will draw the marker.\r\n        this.shapeRenderer = new $.jqplot.ShapeRenderer();\r\n        \r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n        var sdopt = {angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, lineWidth:this.lineWidth, depth:this.shadowDepth, closePath:true};\r\n        if (this.style.indexOf('filled') != -1) {\r\n            sdopt.fill = true;\r\n        }\r\n        if (this.style.indexOf('ircle') != -1) {\r\n            sdopt.isarc = true;\r\n            sdopt.closePath = false;\r\n        }\r\n        this.shadowRenderer.init(sdopt);\r\n        \r\n        var shopt = {fill:false, isarc:false, strokeStyle:this.color, fillStyle:this.color, lineWidth:this.lineWidth, closePath:true};\r\n        if (this.style.indexOf('filled') != -1) {\r\n            shopt.fill = true;\r\n        }\r\n        if (this.style.indexOf('ircle') != -1) {\r\n            shopt.isarc = true;\r\n            shopt.closePath = false;\r\n        }\r\n        this.shapeRenderer.init(shopt);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.drawDiamond = function(x, y, ctx, fill, options) {\r\n        var stretch = 1.2;\r\n        var dx = this.size/2/stretch;\r\n        var dy = this.size/2*stretch;\r\n        var points = [[x-dx, y], [x, y+dy], [x+dx, y], [x, y-dy]];\r\n        if (this.shadow) {\r\n            this.shadowRenderer.draw(ctx, points);\r\n        }\r\n        this.shapeRenderer.draw(ctx, points, options);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.drawPlus = function(x, y, ctx, fill, options) {\r\n        var stretch = 1.0;\r\n        var dx = this.size/2*stretch;\r\n        var dy = this.size/2*stretch;\r\n        var points1 = [[x, y-dy], [x, y+dy]];\r\n        var points2 = [[x+dx, y], [x-dx, y]];\r\n        var opts = $.extend(true, {}, this.options, {closePath:false});\r\n        if (this.shadow) {\r\n            this.shadowRenderer.draw(ctx, points1, {closePath:false});\r\n            this.shadowRenderer.draw(ctx, points2, {closePath:false});\r\n        }\r\n        this.shapeRenderer.draw(ctx, points1, opts);\r\n        this.shapeRenderer.draw(ctx, points2, opts);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.drawX = function(x, y, ctx, fill, options) {\r\n        var stretch = 1.0;\r\n        var dx = this.size/2*stretch;\r\n        var dy = this.size/2*stretch;\r\n        var opts = $.extend(true, {}, this.options, {closePath:false});\r\n        var points1 = [[x-dx, y-dy], [x+dx, y+dy]];\r\n        var points2 = [[x-dx, y+dy], [x+dx, y-dy]];\r\n        if (this.shadow) {\r\n            this.shadowRenderer.draw(ctx, points1, {closePath:false});\r\n            this.shadowRenderer.draw(ctx, points2, {closePath:false});\r\n        }\r\n        this.shapeRenderer.draw(ctx, points1, opts);\r\n        this.shapeRenderer.draw(ctx, points2, opts);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.drawDash = function(x, y, ctx, fill, options) {\r\n        var stretch = 1.0;\r\n        var dx = this.size/2*stretch;\r\n        var dy = this.size/2*stretch;\r\n        var points = [[x-dx, y], [x+dx, y]];\r\n        if (this.shadow) {\r\n            this.shadowRenderer.draw(ctx, points);\r\n        }\r\n        this.shapeRenderer.draw(ctx, points, options);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.drawLine = function(p1, p2, ctx, fill, options) {\r\n        var points = [p1, p2];\r\n        if (this.shadow) {\r\n            this.shadowRenderer.draw(ctx, points);\r\n        }\r\n        this.shapeRenderer.draw(ctx, points, options);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.drawSquare = function(x, y, ctx, fill, options) {\r\n        var stretch = 1.0;\r\n        var dx = this.size/2/stretch;\r\n        var dy = this.size/2*stretch;\r\n        var points = [[x-dx, y-dy], [x-dx, y+dy], [x+dx, y+dy], [x+dx, y-dy]];\r\n        if (this.shadow) {\r\n            this.shadowRenderer.draw(ctx, points);\r\n        }\r\n        this.shapeRenderer.draw(ctx, points, options);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.drawCircle = function(x, y, ctx, fill, options) {\r\n        var radius = this.size/2;\r\n        var end = 2*Math.PI;\r\n        var points = [x, y, radius, 0, end, true];\r\n        if (this.shadow) {\r\n            this.shadowRenderer.draw(ctx, points);\r\n        }\r\n        this.shapeRenderer.draw(ctx, points, options);\r\n    };\r\n    \r\n    $.jqplot.MarkerRenderer.prototype.draw = function(x, y, ctx, options) {\r\n        options = options || {};\r\n        // hack here b/c shape renderer uses canvas based color style options\r\n        // and marker uses css style names.\r\n        if (options.show == null || options.show != false) {\r\n            if (options.color && !options.fillStyle) {\r\n                options.fillStyle = options.color;\r\n            }\r\n            if (options.color && !options.strokeStyle) {\r\n                options.strokeStyle = options.color;\r\n            }\r\n            switch (this.style) {\r\n                case 'diamond':\r\n                    this.drawDiamond(x,y,ctx, false, options);\r\n                    break;\r\n                case 'filledDiamond':\r\n                    this.drawDiamond(x,y,ctx, true, options);\r\n                    break;\r\n                case 'circle':\r\n                    this.drawCircle(x,y,ctx, false, options);\r\n                    break;\r\n                case 'filledCircle':\r\n                    this.drawCircle(x,y,ctx, true, options);\r\n                    break;\r\n                case 'square':\r\n                    this.drawSquare(x,y,ctx, false, options);\r\n                    break;\r\n                case 'filledSquare':\r\n                    this.drawSquare(x,y,ctx, true, options);\r\n                    break;\r\n                case 'x':\r\n                    this.drawX(x,y,ctx, true, options);\r\n                    break;\r\n                case 'plus':\r\n                    this.drawPlus(x,y,ctx, true, options);\r\n                    break;\r\n                case 'dash':\r\n                    this.drawDash(x,y,ctx, true, options);\r\n                    break;\r\n                case 'line':\r\n                    this.drawLine(x, y, ctx, false, options);\r\n                    break;\r\n                default:\r\n                    this.drawDiamond(x,y,ctx, false, options);\r\n                    break;\r\n            }\r\n        }\r\n    };\r\n    \r\n    // class: $.jqplot.shadowRenderer\r\n    // The default jqPlot shadow renderer, rendering shadows behind shapes.\r\n    $.jqplot.ShadowRenderer = function(options){ \r\n        // Group: Properties\r\n        \r\n        // prop: angle\r\n        // Angle of the shadow in degrees.  Measured counter-clockwise from the x axis.\r\n        this.angle = 45;\r\n        // prop: offset\r\n        // Pixel offset at the given shadow angle of each shadow stroke from the last stroke.\r\n        this.offset = 1;\r\n        // prop: alpha\r\n        // alpha transparency of shadow stroke.\r\n        this.alpha = 0.07;\r\n        // prop: lineWidth\r\n        // width of the shadow line stroke.\r\n        this.lineWidth = 1.5;\r\n        // prop: lineJoin\r\n        // How line segments of the shadow are joined.\r\n        this.lineJoin = 'miter';\r\n        // prop: lineCap\r\n        // how ends of the shadow line are rendered.\r\n        this.lineCap = 'round';\r\n        // prop; closePath\r\n        // whether line path segment is closed upon itself.\r\n        this.closePath = false;\r\n        // prop: fill\r\n        // whether to fill the shape.\r\n        this.fill = false;\r\n        // prop: depth\r\n        // how many times the shadow is stroked.  Each stroke will be offset by offset at angle degrees.\r\n        this.depth = 3;\r\n        this.strokeStyle = 'rgba(0,0,0,0.1)';\r\n        // prop: isarc\r\n        // whether the shadow is an arc or not.\r\n        this.isarc = false;\r\n        \r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.ShadowRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    // function: draw\r\n    // draws an transparent black (i.e. gray) shadow.\r\n    //\r\n    // ctx - canvas drawing context\r\n    // points - array of points or [x, y, radius, start angle (rad), end angle (rad)]\r\n    $.jqplot.ShadowRenderer.prototype.draw = function(ctx, points, options) {\r\n        ctx.save();\r\n        var opts = (options != null) ? options : {};\r\n        var fill = (opts.fill != null) ? opts.fill : this.fill;\r\n        var fillRect = (opts.fillRect != null) ? opts.fillRect : this.fillRect;\r\n        var closePath = (opts.closePath != null) ? opts.closePath : this.closePath;\r\n        var offset = (opts.offset != null) ? opts.offset : this.offset;\r\n        var alpha = (opts.alpha != null) ? opts.alpha : this.alpha;\r\n        var depth = (opts.depth != null) ? opts.depth : this.depth;\r\n        var isarc = (opts.isarc != null) ? opts.isarc : this.isarc;\r\n        var linePattern = (opts.linePattern != null) ? opts.linePattern : this.linePattern;\r\n        ctx.lineWidth = (opts.lineWidth != null) ? opts.lineWidth : this.lineWidth;\r\n        ctx.lineJoin = (opts.lineJoin != null) ? opts.lineJoin : this.lineJoin;\r\n        ctx.lineCap = (opts.lineCap != null) ? opts.lineCap : this.lineCap;\r\n        ctx.strokeStyle = opts.strokeStyle || this.strokeStyle || 'rgba(0,0,0,'+alpha+')';\r\n        ctx.fillStyle = opts.fillStyle || this.fillStyle || 'rgba(0,0,0,'+alpha+')';\r\n        for (var j=0; j<depth; j++) {\r\n            var ctxPattern = $.jqplot.LinePattern(ctx, linePattern);\r\n            ctx.translate(Math.cos(this.angle*Math.PI/180)*offset, Math.sin(this.angle*Math.PI/180)*offset);\r\n            ctxPattern.beginPath();\r\n            if (isarc) {\r\n                ctx.arc(points[0], points[1], points[2], points[3], points[4], true);                \r\n            }\r\n            else if (fillRect) {\r\n                if (fillRect) {\r\n                    ctx.fillRect(points[0], points[1], points[2], points[3]);\r\n                }\r\n            }\r\n            else if (points && points.length){\r\n                var move = true;\r\n                for (var i=0; i<points.length; i++) {\r\n                    // skip to the first non-null point and move to it.\r\n                    if (points[i][0] != null && points[i][1] != null) {\r\n                        if (move) {\r\n                            ctxPattern.moveTo(points[i][0], points[i][1]);\r\n                            move = false;\r\n                        }\r\n                        else {\r\n                            ctxPattern.lineTo(points[i][0], points[i][1]);\r\n                        }\r\n                    }\r\n                    else {\r\n                        move = true;\r\n                    }\r\n                }\r\n                \r\n            }\r\n            if (closePath) {\r\n                ctxPattern.closePath();\r\n            }\r\n            if (fill) {\r\n                ctx.fill();\r\n            }\r\n            else {\r\n                ctx.stroke();\r\n            }\r\n        }\r\n        ctx.restore();\r\n    };\r\n    \r\n    // class: $.jqplot.shapeRenderer\r\n    // The default jqPlot shape renderer.  Given a set of points will\r\n    // plot them and either stroke a line (fill = false) or fill them (fill = true).\r\n    // If a filled shape is desired, closePath = true must also be set to close\r\n    // the shape.\r\n    $.jqplot.ShapeRenderer = function(options){\r\n        \r\n        this.lineWidth = 1.5;\r\n        // prop: linePattern\r\n        // line pattern 'dashed', 'dotted', 'solid', some combination\r\n        // of '-' and '.' characters such as '.-.' or a numerical array like \r\n        // [draw, skip, draw, skip, ...] such as [1, 10] to draw a dotted line, \r\n        // [1, 10, 20, 10] to draw a dot-dash line, and so on.\r\n        this.linePattern = 'solid';\r\n        // prop: lineJoin\r\n        // How line segments of the shadow are joined.\r\n        this.lineJoin = 'miter';\r\n        // prop: lineCap\r\n        // how ends of the shadow line are rendered.\r\n        this.lineCap = 'round';\r\n        // prop; closePath\r\n        // whether line path segment is closed upon itself.\r\n        this.closePath = false;\r\n        // prop: fill\r\n        // whether to fill the shape.\r\n        this.fill = false;\r\n        // prop: isarc\r\n        // whether the shadow is an arc or not.\r\n        this.isarc = false;\r\n        // prop: fillRect\r\n        // true to draw shape as a filled rectangle.\r\n        this.fillRect = false;\r\n        // prop: strokeRect\r\n        // true to draw shape as a stroked rectangle.\r\n        this.strokeRect = false;\r\n        // prop: clearRect\r\n        // true to cear a rectangle.\r\n        this.clearRect = false;\r\n        // prop: strokeStyle\r\n        // css color spec for the stoke style\r\n        this.strokeStyle = '#999999';\r\n        // prop: fillStyle\r\n        // css color spec for the fill style.\r\n        this.fillStyle = '#999999'; \r\n        \r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.ShapeRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    // function: draw\r\n    // draws the shape.\r\n    //\r\n    // ctx - canvas drawing context\r\n    // points - array of points for shapes or \r\n    // [x, y, width, height] for rectangles or\r\n    // [x, y, radius, start angle (rad), end angle (rad)] for circles and arcs.\r\n    $.jqplot.ShapeRenderer.prototype.draw = function(ctx, points, options) {\r\n        ctx.save();\r\n        var opts = (options != null) ? options : {};\r\n        var fill = (opts.fill != null) ? opts.fill : this.fill;\r\n        var closePath = (opts.closePath != null) ? opts.closePath : this.closePath;\r\n        var fillRect = (opts.fillRect != null) ? opts.fillRect : this.fillRect;\r\n        var strokeRect = (opts.strokeRect != null) ? opts.strokeRect : this.strokeRect;\r\n        var clearRect = (opts.clearRect != null) ? opts.clearRect : this.clearRect;\r\n        var isarc = (opts.isarc != null) ? opts.isarc : this.isarc;\r\n        var linePattern = (opts.linePattern != null) ? opts.linePattern : this.linePattern;\r\n        var ctxPattern = $.jqplot.LinePattern(ctx, linePattern);\r\n        ctx.lineWidth = opts.lineWidth || this.lineWidth;\r\n        ctx.lineJoin = opts.lineJoin || this.lineJoin;\r\n        ctx.lineCap = opts.lineCap || this.lineCap;\r\n        ctx.strokeStyle = (opts.strokeStyle || opts.color) || this.strokeStyle;\r\n        ctx.fillStyle = opts.fillStyle || this.fillStyle;\r\n        ctx.beginPath();\r\n        if (isarc) {\r\n            ctx.arc(points[0], points[1], points[2], points[3], points[4], true);   \r\n            if (closePath) {\r\n                ctx.closePath();\r\n            }\r\n            if (fill) {\r\n                ctx.fill();\r\n            }\r\n            else {\r\n                ctx.stroke();\r\n            }\r\n            ctx.restore();\r\n            return;\r\n        }\r\n        else if (clearRect) {\r\n            ctx.clearRect(points[0], points[1], points[2], points[3]);\r\n            ctx.restore();\r\n            return;\r\n        }\r\n        else if (fillRect || strokeRect) {\r\n            if (fillRect) {\r\n                ctx.fillRect(points[0], points[1], points[2], points[3]);\r\n            }\r\n            if (strokeRect) {\r\n                ctx.strokeRect(points[0], points[1], points[2], points[3]);\r\n                ctx.restore();\r\n                return;\r\n            }\r\n        }\r\n        else if (points && points.length){\r\n            var move = true;\r\n            for (var i=0; i<points.length; i++) {\r\n                // skip to the first non-null point and move to it.\r\n                if (points[i][0] != null && points[i][1] != null) {\r\n                    if (move) {\r\n                        ctxPattern.moveTo(points[i][0], points[i][1]);\r\n                        move = false;\r\n                    }\r\n                    else {\r\n                        ctxPattern.lineTo(points[i][0], points[i][1]);\r\n                    }\r\n                }\r\n                else {\r\n                    move = true;\r\n                }\r\n            }\r\n            if (closePath) {\r\n                ctxPattern.closePath();\r\n            }\r\n            if (fill) {\r\n                ctx.fill();\r\n            }\r\n            else {\r\n                ctx.stroke();\r\n            }\r\n        }\r\n        ctx.restore();\r\n    };\r\n    \r\n    // class $.jqplot.TableLegendRenderer\r\n    // The default legend renderer for jqPlot.\r\n    $.jqplot.TableLegendRenderer = function(){\r\n        //\r\n    };\r\n    \r\n    $.jqplot.TableLegendRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n    };\r\n        \r\n    $.jqplot.TableLegendRenderer.prototype.addrow = function (label, color, pad, reverse) {\r\n        var rs = (pad) ? this.rowSpacing+'px' : '0px';\r\n        var tr;\r\n        var td;\r\n        var elem;\r\n        var div0;\r\n        var div1;\r\n        elem = document.createElement('tr');\r\n        tr = $(elem);\r\n        tr.addClass('jqplot-table-legend');\r\n        elem = null;\r\n\r\n        if (reverse){\r\n            tr.prependTo(this._elem);\r\n        }\r\n\r\n        else{\r\n            tr.appendTo(this._elem);\r\n        }\r\n\r\n        if (this.showSwatches) {\r\n            td = $(document.createElement('td'));\r\n            td.addClass('jqplot-table-legend jqplot-table-legend-swatch');\r\n            td.css({textAlign: 'center', paddingTop: rs});\r\n\r\n            div0 = $(document.createElement('div'));\r\n            div0.addClass('jqplot-table-legend-swatch-outline');\r\n            div1 = $(document.createElement('div'));\r\n            div1.addClass('jqplot-table-legend-swatch');\r\n            div1.css({backgroundColor: color, borderColor: color});\r\n\r\n            tr.append(td.append(div0.append(div1)));\r\n\r\n            // $('<td class=\"jqplot-table-legend\" style=\"text-align:center;padding-top:'+rs+';\">'+\r\n            // '<div><div class=\"jqplot-table-legend-swatch\" style=\"background-color:'+color+';border-color:'+color+';\"></div>'+\r\n            // '</div></td>').appendTo(tr);\r\n        }\r\n        if (this.showLabels) {\r\n            td = $(document.createElement('td'));\r\n            td.addClass('jqplot-table-legend jqplot-table-legend-label');\r\n            td.css('paddingTop', rs);\r\n            tr.append(td);\r\n\r\n            // elem = $('<td class=\"jqplot-table-legend\" style=\"padding-top:'+rs+';\"></td>');\r\n            // elem.appendTo(tr);\r\n            if (this.escapeHtml) {\r\n                td.text(label);\r\n            }\r\n            else {\r\n                td.html(label);\r\n            }\r\n        }\r\n        td = null;\r\n        div0 = null;\r\n        div1 = null;\r\n        tr = null;\r\n        elem = null;\r\n    };\r\n    \r\n    // called with scope of legend\r\n    $.jqplot.TableLegendRenderer.prototype.draw = function() {\r\n        if (this._elem) {\r\n            this._elem.emptyForce();\r\n            this._elem = null;\r\n        }\r\n\r\n        if (this.show) {\r\n            var series = this._series;\r\n            // make a table.  one line label per row.\r\n            var elem = document.createElement('table');\r\n            this._elem = $(elem);\r\n            this._elem.addClass('jqplot-table-legend');\r\n\r\n            var ss = {position:'absolute'};\r\n            if (this.background) {\r\n                ss['background'] = this.background;\r\n            }\r\n            if (this.border) {\r\n                ss['border'] = this.border;\r\n            }\r\n            if (this.fontSize) {\r\n                ss['fontSize'] = this.fontSize;\r\n            }\r\n            if (this.fontFamily) {\r\n                ss['fontFamily'] = this.fontFamily;\r\n            }\r\n            if (this.textColor) {\r\n                ss['textColor'] = this.textColor;\r\n            }\r\n            if (this.marginTop != null) {\r\n                ss['marginTop'] = this.marginTop;\r\n            }\r\n            if (this.marginBottom != null) {\r\n                ss['marginBottom'] = this.marginBottom;\r\n            }\r\n            if (this.marginLeft != null) {\r\n                ss['marginLeft'] = this.marginLeft;\r\n            }\r\n            if (this.marginRight != null) {\r\n                ss['marginRight'] = this.marginRight;\r\n            }\r\n            \r\n        \r\n            var pad = false, \r\n                reverse = false,\r\n                s;\r\n            for (var i = 0; i< series.length; i++) {\r\n                s = series[i];\r\n                if (s._stack || s.renderer.constructor == $.jqplot.BezierCurveRenderer){\r\n                    reverse = true;\r\n                }\r\n                if (s.show && s.showLabel) {\r\n                    var lt = this.labels[i] || s.label.toString();\r\n                    if (lt) {\r\n                        var color = s.color;\r\n                        if (reverse && i < series.length - 1){\r\n                            pad = true;\r\n                        }\r\n                        else if (reverse && i == series.length - 1){\r\n                            pad = false;\r\n                        }\r\n                        this.renderer.addrow.call(this, lt, color, pad, reverse);\r\n                        pad = true;\r\n                    }\r\n                    // let plugins add more rows to legend.  Used by trend line plugin.\r\n                    for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) {\r\n                        var item = $.jqplot.addLegendRowHooks[j].call(this, s);\r\n                        if (item) {\r\n                            this.renderer.addrow.call(this, item.label, item.color, pad);\r\n                            pad = true;\r\n                        } \r\n                    }\r\n                    lt = null;\r\n                }\r\n            }\r\n        }\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.TableLegendRenderer.prototype.pack = function(offsets) {\r\n        if (this.show) {       \r\n            if (this.placement == 'insideGrid') {\r\n                switch (this.location) {\r\n                    case 'nw':\r\n                        var a = offsets.left;\r\n                        var b = offsets.top;\r\n                        this._elem.css('left', a);\r\n                        this._elem.css('top', b);\r\n                        break;\r\n                    case 'n':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = offsets.top;\r\n                        this._elem.css('left', a);\r\n                        this._elem.css('top', b);\r\n                        break;\r\n                    case 'ne':\r\n                        var a = offsets.right;\r\n                        var b = offsets.top;\r\n                        this._elem.css({right:a, top:b});\r\n                        break;\r\n                    case 'e':\r\n                        var a = offsets.right;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({right:a, top:b});\r\n                        break;\r\n                    case 'se':\r\n                        var a = offsets.right;\r\n                        var b = offsets.bottom;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                    case 's':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = offsets.bottom;\r\n                        this._elem.css({left:a, bottom:b});\r\n                        break;\r\n                    case 'sw':\r\n                        var a = offsets.left;\r\n                        var b = offsets.bottom;\r\n                        this._elem.css({left:a, bottom:b});\r\n                        break;\r\n                    case 'w':\r\n                        var a = offsets.left;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    default:  // same as 'se'\r\n                        var a = offsets.right;\r\n                        var b = offsets.bottom;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                }\r\n                \r\n            }\r\n            else if (this.placement == 'outside'){\r\n                switch (this.location) {\r\n                    case 'nw':\r\n                        var a = this._plotDimensions.width - offsets.left;\r\n                        var b = offsets.top;\r\n                        this._elem.css('right', a);\r\n                        this._elem.css('top', b);\r\n                        break;\r\n                    case 'n':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = this._plotDimensions.height - offsets.top;\r\n                        this._elem.css('left', a);\r\n                        this._elem.css('bottom', b);\r\n                        break;\r\n                    case 'ne':\r\n                        var a = this._plotDimensions.width - offsets.right;\r\n                        var b = offsets.top;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    case 'e':\r\n                        var a = this._plotDimensions.width - offsets.right;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    case 'se':\r\n                        var a = this._plotDimensions.width - offsets.right;\r\n                        var b = offsets.bottom;\r\n                        this._elem.css({left:a, bottom:b});\r\n                        break;\r\n                    case 's':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = this._plotDimensions.height - offsets.bottom;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    case 'sw':\r\n                        var a = this._plotDimensions.width - offsets.left;\r\n                        var b = offsets.bottom;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                    case 'w':\r\n                        var a = this._plotDimensions.width - offsets.left;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({right:a, top:b});\r\n                        break;\r\n                    default:  // same as 'se'\r\n                        var a = offsets.right;\r\n                        var b = offsets.bottom;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                }\r\n            }\r\n            else {\r\n                switch (this.location) {\r\n                    case 'nw':\r\n                        this._elem.css({left:0, top:offsets.top});\r\n                        break;\r\n                    case 'n':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        this._elem.css({left: a, top:offsets.top});\r\n                        break;\r\n                    case 'ne':\r\n                        this._elem.css({right:0, top:offsets.top});\r\n                        break;\r\n                    case 'e':\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({right:offsets.right, top:b});\r\n                        break;\r\n                    case 'se':\r\n                        this._elem.css({right:offsets.right, bottom:offsets.bottom});\r\n                        break;\r\n                    case 's':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        this._elem.css({left: a, bottom:offsets.bottom});\r\n                        break;\r\n                    case 'sw':\r\n                        this._elem.css({left:offsets.left, bottom:offsets.bottom});\r\n                        break;\r\n                    case 'w':\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({left:offsets.left, top:b});\r\n                        break;\r\n                    default:  // same as 'se'\r\n                        this._elem.css({right:offsets.right, bottom:offsets.bottom});\r\n                        break;\r\n                }\r\n            }\r\n        } \r\n    };\r\n\r\n    /**\r\n     * Class: $.jqplot.ThemeEngine\r\n     * Theme Engine provides a programatic way to change some of the  more\r\n     * common jqplot styling options such as fonts, colors and grid options.\r\n     * A theme engine instance is created with each plot.  The theme engine\r\n     * manages a collection of themes which can be modified, added to, or \r\n     * applied to the plot.\r\n     * \r\n     * The themeEngine class is not instantiated directly.\r\n     * When a plot is initialized, the current plot options are scanned\r\n     * an a default theme named \"Default\" is created.  This theme is\r\n     * used as the basis for other themes added to the theme engine and\r\n     * is always available.\r\n     * \r\n     * A theme is a simple javascript object with styling parameters for\r\n     * various entities of the plot.  A theme has the form:\r\n     * \r\n     * \r\n     * > {\r\n     * >     _name:f \"Default\",\r\n     * >     target: {\r\n     * >         backgroundColor: \"transparent\"\r\n     * >     },\r\n     * >     legend: {\r\n     * >         textColor: null,\r\n     * >         fontFamily: null,\r\n     * >         fontSize: null,\r\n     * >         border: null,\r\n     * >         background: null\r\n     * >     },\r\n     * >     title: {\r\n     * >         textColor: \"rgb(102, 102, 102)\",\r\n     * >         fontFamily: \"'Trebuchet MS',Arial,Helvetica,sans-serif\",\r\n     * >         fontSize: \"19.2px\",\r\n     * >         textAlign: \"center\"\r\n     * >     },\r\n     * >     seriesStyles: {},\r\n     * >     series: [{\r\n     * >         color: \"#4bb2c5\",\r\n     * >         lineWidth: 2.5,\r\n     * >         linePattern: \"solid\",\r\n     * >         shadow: true,\r\n     * >         fillColor: \"#4bb2c5\",\r\n     * >         showMarker: true,\r\n     * >         markerOptions: {\r\n     * >             color: \"#4bb2c5\",\r\n     * >             show: true,\r\n     * >             style: 'filledCircle',\r\n     * >             lineWidth: 1.5,\r\n     * >             size: 4,\r\n     * >             shadow: true\r\n     * >         }\r\n     * >     }],\r\n     * >     grid: {\r\n     * >         drawGridlines: true,\r\n     * >         gridLineColor: \"#cccccc\",\r\n     * >         gridLineWidth: 1,\r\n     * >         backgroundColor: \"#fffdf6\",\r\n     * >         borderColor: \"#999999\",\r\n     * >         borderWidth: 2,\r\n     * >         shadow: true\r\n     * >     },\r\n     * >     axesStyles: {\r\n     * >         label: {},\r\n     * >         ticks: {}\r\n     * >     },\r\n     * >     axes: {\r\n     * >         xaxis: {\r\n     * >             borderColor: \"#999999\",\r\n     * >             borderWidth: 2,\r\n     * >             ticks: {\r\n     * >                 show: true,\r\n     * >                 showGridline: true,\r\n     * >                 showLabel: true,\r\n     * >                 showMark: true,\r\n     * >                 size: 4,\r\n     * >                 textColor: \"\",\r\n     * >                 whiteSpace: \"nowrap\",\r\n     * >                 fontSize: \"12px\",\r\n     * >                 fontFamily: \"'Trebuchet MS',Arial,Helvetica,sans-serif\"\r\n     * >             },\r\n     * >             label: {\r\n     * >                 textColor: \"rgb(102, 102, 102)\",\r\n     * >                 whiteSpace: \"normal\",\r\n     * >                 fontSize: \"14.6667px\",\r\n     * >                 fontFamily: \"'Trebuchet MS',Arial,Helvetica,sans-serif\",\r\n     * >                 fontWeight: \"400\"\r\n     * >             }\r\n     * >         },\r\n     * >         yaxis: {\r\n     * >             borderColor: \"#999999\",\r\n     * >             borderWidth: 2,\r\n     * >             ticks: {\r\n     * >                 show: true,\r\n     * >                 showGridline: true,\r\n     * >                 showLabel: true,\r\n     * >                 showMark: true,\r\n     * >                 size: 4,\r\n     * >                 textColor: \"\",\r\n     * >                 whiteSpace: \"nowrap\",\r\n     * >                 fontSize: \"12px\",\r\n     * >                 fontFamily: \"'Trebuchet MS',Arial,Helvetica,sans-serif\"\r\n     * >             },\r\n     * >             label: {\r\n     * >                 textColor: null,\r\n     * >                 whiteSpace: null,\r\n     * >                 fontSize: null,\r\n     * >                 fontFamily: null,\r\n     * >                 fontWeight: null\r\n     * >             }\r\n     * >         },\r\n     * >         x2axis: {...\r\n     * >         },\r\n     * >         ...\r\n     * >         y9axis: {...\r\n     * >         }\r\n     * >     }\r\n     * > }\r\n     * \r\n     * \"seriesStyles\" is a style object that will be applied to all series in the plot.\r\n     * It will forcibly override any styles applied on the individual series.  \"axesStyles\" is\r\n     * a style object that will be applied to all axes in the plot.  It will also forcibly\r\n     * override any styles on the individual axes.\r\n     * \r\n     * The example shown above has series options for a line series.  Options for other\r\n     * series types are shown below:\r\n     * \r\n     * Bar Series:\r\n     * \r\n     * > {\r\n     * >     color: \"#4bb2c5\",\r\n     * >     seriesColors: [\"#4bb2c5\", \"#EAA228\", \"#c5b47f\", \"#579575\", \"#839557\", \"#958c12\", \"#953579\", \"#4b5de4\", \"#d8b83f\", \"#ff5800\", \"#0085cc\", \"#c747a3\", \"#cddf54\", \"#FBD178\", \"#26B4E3\", \"#bd70c7\"],\r\n     * >     lineWidth: 2.5,\r\n     * >     shadow: true,\r\n     * >     barPadding: 2,\r\n     * >     barMargin: 10,\r\n     * >     barWidth: 15.09375,\r\n     * >     highlightColors: [\"rgb(129,201,214)\", \"rgb(129,201,214)\", \"rgb(129,201,214)\", \"rgb(129,201,214)\", \"rgb(129,201,214)\", \"rgb(129,201,214)\", \"rgb(129,201,214)\", \"rgb(129,201,214)\"]\r\n     * > }\r\n     * \r\n     * Pie Series:\r\n     * \r\n     * > {\r\n     * >     seriesColors: [\"#4bb2c5\", \"#EAA228\", \"#c5b47f\", \"#579575\", \"#839557\", \"#958c12\", \"#953579\", \"#4b5de4\", \"#d8b83f\", \"#ff5800\", \"#0085cc\", \"#c747a3\", \"#cddf54\", \"#FBD178\", \"#26B4E3\", \"#bd70c7\"],\r\n     * >     padding: 20,\r\n     * >     sliceMargin: 0,\r\n     * >     fill: true,\r\n     * >     shadow: true,\r\n     * >     startAngle: 0,\r\n     * >     lineWidth: 2.5,\r\n     * >     highlightColors: [\"rgb(129,201,214)\", \"rgb(240,189,104)\", \"rgb(214,202,165)\", \"rgb(137,180,158)\", \"rgb(168,180,137)\", \"rgb(180,174,89)\", \"rgb(180,113,161)\", \"rgb(129,141,236)\", \"rgb(227,205,120)\", \"rgb(255,138,76)\", \"rgb(76,169,219)\", \"rgb(215,126,190)\", \"rgb(220,232,135)\", \"rgb(200,167,96)\", \"rgb(103,202,235)\", \"rgb(208,154,215)\"]\r\n     * > }\r\n     * \r\n     * Funnel Series:\r\n     * \r\n     * > {\r\n     * >     color: \"#4bb2c5\",\r\n     * >     lineWidth: 2,\r\n     * >     shadow: true,\r\n     * >     padding: {\r\n     * >         top: 20,\r\n     * >         right: 20,\r\n     * >         bottom: 20,\r\n     * >         left: 20\r\n     * >     },\r\n     * >     sectionMargin: 6,\r\n     * >     seriesColors: [\"#4bb2c5\", \"#EAA228\", \"#c5b47f\", \"#579575\", \"#839557\", \"#958c12\", \"#953579\", \"#4b5de4\", \"#d8b83f\", \"#ff5800\", \"#0085cc\", \"#c747a3\", \"#cddf54\", \"#FBD178\", \"#26B4E3\", \"#bd70c7\"],\r\n     * >     highlightColors: [\"rgb(147,208,220)\", \"rgb(242,199,126)\", \"rgb(220,210,178)\", \"rgb(154,191,172)\", \"rgb(180,191,154)\", \"rgb(191,186,112)\", \"rgb(191,133,174)\", \"rgb(147,157,238)\", \"rgb(231,212,139)\", \"rgb(255,154,102)\", \"rgb(102,181,224)\", \"rgb(221,144,199)\", \"rgb(225,235,152)\", \"rgb(200,167,96)\", \"rgb(124,210,238)\", \"rgb(215,169,221)\"]\r\n     * > }\r\n     * \r\n     */\r\n    $.jqplot.ThemeEngine = function(){\r\n        // Group: Properties\r\n        //\r\n        // prop: themes\r\n        // hash of themes managed by the theme engine.  \r\n        // Indexed by theme name.\r\n        this.themes = {};\r\n        // prop: activeTheme\r\n        // Pointer to currently active theme\r\n        this.activeTheme=null;\r\n        \r\n    };\r\n    \r\n    // called with scope of plot\r\n    $.jqplot.ThemeEngine.prototype.init = function() {\r\n        // get the Default theme from the current plot settings.\r\n        var th = new $.jqplot.Theme({_name:'Default'});\r\n        var n, i, nn;\r\n        \r\n        for (n in th.target) {\r\n            if (n == \"textColor\") {\r\n                th.target[n] = this.target.css('color');\r\n            }\r\n            else {\r\n                th.target[n] = this.target.css(n);\r\n            }\r\n        }\r\n        \r\n        if (this.title.show && this.title._elem) {\r\n            for (n in th.title) {\r\n                if (n == \"textColor\") {\r\n                    th.title[n] = this.title._elem.css('color');\r\n                }\r\n                else {\r\n                    th.title[n] = this.title._elem.css(n);\r\n                }\r\n            }\r\n        }\r\n        \r\n        for (n in th.grid) {\r\n            th.grid[n] = this.grid[n];\r\n        }\r\n        if (th.grid.backgroundColor == null && this.grid.background != null) {\r\n            th.grid.backgroundColor = this.grid.background;\r\n        }\r\n        if (this.legend.show && this.legend._elem) {\r\n            for (n in th.legend) {\r\n                if (n == 'textColor') {\r\n                    th.legend[n] = this.legend._elem.css('color');\r\n                }\r\n                else {\r\n                    th.legend[n] = this.legend._elem.css(n);\r\n                }\r\n            }\r\n        }\r\n        var s;\r\n        \r\n        for (i=0; i<this.series.length; i++) {\r\n            s = this.series[i];\r\n            if (s.renderer.constructor == $.jqplot.LineRenderer) {\r\n                th.series.push(new LineSeriesProperties());\r\n            }\r\n            else if (s.renderer.constructor == $.jqplot.BarRenderer) {\r\n                th.series.push(new BarSeriesProperties());\r\n            }\r\n            else if (s.renderer.constructor == $.jqplot.PieRenderer) {\r\n                th.series.push(new PieSeriesProperties());\r\n            }\r\n            else if (s.renderer.constructor == $.jqplot.DonutRenderer) {\r\n                th.series.push(new DonutSeriesProperties());\r\n            }\r\n            else if (s.renderer.constructor == $.jqplot.FunnelRenderer) {\r\n                th.series.push(new FunnelSeriesProperties());\r\n            }\r\n            else if (s.renderer.constructor == $.jqplot.MeterGaugeRenderer) {\r\n                th.series.push(new MeterSeriesProperties());\r\n            }\r\n            else {\r\n                th.series.push({});\r\n            }\r\n            for (n in th.series[i]) {\r\n                th.series[i][n] = s[n];\r\n            }\r\n        }\r\n        var a, ax;\r\n        for (n in this.axes) {\r\n            ax = this.axes[n];\r\n            a = th.axes[n] = new AxisProperties();\r\n            a.borderColor = ax.borderColor;\r\n            a.borderWidth = ax.borderWidth;\r\n            if (ax._ticks && ax._ticks[0]) {\r\n                for (nn in a.ticks) {\r\n                    if (ax._ticks[0].hasOwnProperty(nn)) {\r\n                        a.ticks[nn] = ax._ticks[0][nn];\r\n                    }\r\n                    else if (ax._ticks[0]._elem){\r\n                        a.ticks[nn] = ax._ticks[0]._elem.css(nn);\r\n                    }\r\n                }\r\n            }\r\n            if (ax._label && ax._label.show) {\r\n                for (nn in a.label) {\r\n                    // a.label[nn] = ax._label._elem.css(nn);\r\n                    if (ax._label[nn]) {\r\n                        a.label[nn] = ax._label[nn];\r\n                    }\r\n                    else if (ax._label._elem){\r\n                        if (nn == 'textColor') {\r\n                            a.label[nn] = ax._label._elem.css('color');\r\n                        }\r\n                        else {\r\n                            a.label[nn] = ax._label._elem.css(nn);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        this.themeEngine._add(th);\r\n        this.themeEngine.activeTheme  = this.themeEngine.themes[th._name];\r\n    };\r\n    /**\r\n     * Group: methods\r\n     * \r\n     * method: get\r\n     * \r\n     * Get and return the named theme or the active theme if no name given.\r\n     * \r\n     * parameter:\r\n     * \r\n     * name - name of theme to get.\r\n     * \r\n     * returns:\r\n     * \r\n     * Theme instance of given name.\r\n     */   \r\n    $.jqplot.ThemeEngine.prototype.get = function(name) {\r\n        if (!name) {\r\n            // return the active theme\r\n            return this.activeTheme;\r\n        }\r\n        else {\r\n            return this.themes[name];\r\n        }\r\n    };\r\n    \r\n    function numericalOrder(a,b) { return a-b; }\r\n    \r\n    /**\r\n     * method: getThemeNames\r\n     * \r\n     * Return the list of theme names in this manager in alpha-numerical order.\r\n     * \r\n     * parameter:\r\n     * \r\n     * None\r\n     * \r\n     * returns:\r\n     * \r\n     * A the list of theme names in this manager in alpha-numerical order.\r\n     */       \r\n    $.jqplot.ThemeEngine.prototype.getThemeNames = function() {\r\n        var tn = [];\r\n        for (var n in this.themes) {\r\n            tn.push(n);\r\n        }\r\n        return tn.sort(numericalOrder);\r\n    };\r\n\r\n    /**\r\n     * method: getThemes\r\n     * \r\n     * Return a list of themes in alpha-numerical order by name.\r\n     * \r\n     * parameter:\r\n     * \r\n     * None\r\n     * \r\n     * returns:\r\n     * \r\n     * A list of themes in alpha-numerical order by name.\r\n     */ \r\n    $.jqplot.ThemeEngine.prototype.getThemes = function() {\r\n        var tn = [];\r\n        var themes = [];\r\n        for (var n in this.themes) {\r\n            tn.push(n);\r\n        }\r\n        tn.sort(numericalOrder);\r\n        for (var i=0; i<tn.length; i++) {\r\n            themes.push(this.themes[tn[i]]);\r\n        }\r\n        return themes;\r\n    };\r\n    \r\n    $.jqplot.ThemeEngine.prototype.activate = function(plot, name) {\r\n        // sometimes need to redraw whole plot.\r\n        var redrawPlot = false;\r\n        if (!name && this.activeTheme && this.activeTheme._name) {\r\n            name = this.activeTheme._name;\r\n        }\r\n        if (!this.themes.hasOwnProperty(name)) {\r\n            throw new Error(\"No theme of that name\");\r\n        }\r\n        else {\r\n            var th = this.themes[name];\r\n            this.activeTheme = th;\r\n            var val, checkBorderColor = false, checkBorderWidth = false;\r\n            var arr = ['xaxis', 'x2axis', 'yaxis', 'y2axis'];\r\n            \r\n            for (i=0; i<arr.length; i++) {\r\n                var ax = arr[i];\r\n                if (th.axesStyles.borderColor != null) {\r\n                    plot.axes[ax].borderColor = th.axesStyles.borderColor;\r\n                }\r\n                if (th.axesStyles.borderWidth != null) {\r\n                    plot.axes[ax].borderWidth = th.axesStyles.borderWidth;\r\n                }\r\n            }\r\n            \r\n            for (var axname in plot.axes) {\r\n                var axis = plot.axes[axname];\r\n                if (axis.show) {\r\n                    var thaxis = th.axes[axname] || {};\r\n                    var thaxstyle = th.axesStyles;\r\n                    var thax = $.jqplot.extend(true, {}, thaxis, thaxstyle);\r\n                    val = (th.axesStyles.borderColor != null) ? th.axesStyles.borderColor : thax.borderColor;\r\n                    if (thax.borderColor != null) {\r\n                        axis.borderColor = thax.borderColor;\r\n                        redrawPlot = true;\r\n                    }\r\n                    val = (th.axesStyles.borderWidth != null) ? th.axesStyles.borderWidth : thax.borderWidth;\r\n                    if (thax.borderWidth != null) {\r\n                        axis.borderWidth = thax.borderWidth;\r\n                        redrawPlot = true;\r\n                    }\r\n                    if (axis._ticks && axis._ticks[0]) {\r\n                        for (var nn in thax.ticks) {\r\n                            // val = null;\r\n                            // if (th.axesStyles.ticks && th.axesStyles.ticks[nn] != null) {\r\n                            //     val = th.axesStyles.ticks[nn];\r\n                            // }\r\n                            // else if (thax.ticks[nn] != null){\r\n                            //     val = thax.ticks[nn]\r\n                            // }\r\n                            val = thax.ticks[nn];\r\n                            if (val != null) {\r\n                                axis.tickOptions[nn] = val;\r\n                                axis._ticks = [];\r\n                                redrawPlot = true;\r\n                            }\r\n                        }\r\n                    }\r\n                    if (axis._label && axis._label.show) {\r\n                        for (var nn in thax.label) {\r\n                            // val = null;\r\n                            // if (th.axesStyles.label && th.axesStyles.label[nn] != null) {\r\n                            //     val = th.axesStyles.label[nn];\r\n                            // }\r\n                            // else if (thax.label && thax.label[nn] != null){\r\n                            //     val = thax.label[nn]\r\n                            // }\r\n                            val = thax.label[nn];\r\n                            if (val != null) {\r\n                                axis.labelOptions[nn] = val;\r\n                                redrawPlot = true;\r\n                            }\r\n                        }\r\n                    }\r\n                    \r\n                }\r\n            }            \r\n            \r\n            for (var n in th.grid) {\r\n                if (th.grid[n] != null) {\r\n                    plot.grid[n] = th.grid[n];\r\n                }\r\n            }\r\n            if (!redrawPlot) {\r\n                plot.grid.draw();\r\n            }\r\n            \r\n            if (plot.legend.show) { \r\n                for (n in th.legend) {\r\n                    if (th.legend[n] != null) {\r\n                        plot.legend[n] = th.legend[n];\r\n                    }\r\n                }\r\n            }\r\n            if (plot.title.show) {\r\n                for (n in th.title) {\r\n                    if (th.title[n] != null) {\r\n                        plot.title[n] = th.title[n];\r\n                    }\r\n                }\r\n            }\r\n            \r\n            var i;\r\n            for (i=0; i<th.series.length; i++) {\r\n                var opts = {};\r\n                var redrawSeries = false;\r\n                for (n in th.series[i]) {\r\n                    val = (th.seriesStyles[n] != null) ? th.seriesStyles[n] : th.series[i][n];\r\n                    if (val != null) {\r\n                        opts[n] = val;\r\n                        if (n == 'color') {\r\n                            plot.series[i].renderer.shapeRenderer.fillStyle = val;\r\n                            plot.series[i].renderer.shapeRenderer.strokeStyle = val;\r\n                            plot.series[i][n] = val;\r\n                        }\r\n                        else if ((n == 'lineWidth') || (n == 'linePattern')) {\r\n                            plot.series[i].renderer.shapeRenderer[n] = val;\r\n                            plot.series[i][n] = val;\r\n                        }\r\n                        else if (n == 'markerOptions') {\r\n                            merge (plot.series[i].markerOptions, val);\r\n                            merge (plot.series[i].markerRenderer, val);\r\n                        }\r\n                        else {\r\n                            plot.series[i][n] = val;\r\n                        }\r\n                        redrawPlot = true;\r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (redrawPlot) {\r\n                plot.target.empty();\r\n                plot.draw();\r\n            }\r\n            \r\n            for (n in th.target) {\r\n                if (th.target[n] != null) {\r\n                    plot.target.css(n, th.target[n]);\r\n                }\r\n            }\r\n        }\r\n        \r\n    };\r\n    \r\n    $.jqplot.ThemeEngine.prototype._add = function(theme, name) {\r\n        if (name) {\r\n            theme._name = name;\r\n        }\r\n        if (!theme._name) {\r\n            theme._name = Date.parse(new Date());\r\n        }\r\n        if (!this.themes.hasOwnProperty(theme._name)) {\r\n            this.themes[theme._name] = theme;\r\n        }\r\n        else {\r\n            throw new Error(\"jqplot.ThemeEngine Error: Theme already in use\");\r\n        }\r\n    };\r\n    \r\n    // method remove\r\n    // Delete the named theme, return true on success, false on failure.\r\n    \r\n\r\n    /**\r\n     * method: remove\r\n     * \r\n     * Remove the given theme from the themeEngine.\r\n     * \r\n     * parameters:\r\n     * \r\n     * name - name of the theme to remove.\r\n     * \r\n     * returns:\r\n     * \r\n     * true on success, false on failure.\r\n     */\r\n    $.jqplot.ThemeEngine.prototype.remove = function(name) {\r\n        if (name == 'Default') {\r\n            return false;\r\n        }\r\n        return delete this.themes[name];\r\n    };\r\n\r\n    /**\r\n     * method: newTheme\r\n     * \r\n     * Create a new theme based on the default theme, adding it the themeEngine.\r\n     * \r\n     * parameters:\r\n     * \r\n     * name - name of the new theme.\r\n     * obj - optional object of styles to be applied to this new theme.\r\n     * \r\n     * returns:\r\n     * \r\n     * new Theme object.\r\n     */\r\n    $.jqplot.ThemeEngine.prototype.newTheme = function(name, obj) {\r\n        if (typeof(name) == 'object') {\r\n            obj = obj || name;\r\n            name = null;\r\n        }\r\n        if (obj && obj._name) {\r\n            name = obj._name;\r\n        }\r\n        else {\r\n            name = name || Date.parse(new Date());\r\n        }\r\n        // var th = new $.jqplot.Theme(name);\r\n        var th = this.copy(this.themes['Default']._name, name);\r\n        $.jqplot.extend(th, obj);\r\n        return th;\r\n    };\r\n    \r\n    // function clone(obj) {\r\n    //     return eval(obj.toSource());\r\n    // }\r\n    \r\n    function clone(obj){\r\n        if(obj == null || typeof(obj) != 'object'){\r\n            return obj;\r\n        }\r\n    \r\n        var temp = new obj.constructor();\r\n        for(var key in obj){\r\n            temp[key] = clone(obj[key]);\r\n        }   \r\n        return temp;\r\n    }\r\n    \r\n    $.jqplot.clone = clone;\r\n    \r\n    function merge(obj1, obj2) {\r\n        if (obj2 ==  null || typeof(obj2) != 'object') {\r\n            return;\r\n        }\r\n        for (var key in obj2) {\r\n            if (key == 'highlightColors') {\r\n                obj1[key] = clone(obj2[key]);\r\n            }\r\n            if (obj2[key] != null && typeof(obj2[key]) == 'object') {\r\n                if (!obj1.hasOwnProperty(key)) {\r\n                    obj1[key] = {};\r\n                }\r\n                merge(obj1[key], obj2[key]);\r\n            }\r\n            else {\r\n                obj1[key] = obj2[key];\r\n            }\r\n        }\r\n    }\r\n    \r\n    $.jqplot.merge = merge;\r\n    \r\n        // Use the jQuery 1.3.2 extend function since behaviour in jQuery 1.4 seems problematic\r\n    $.jqplot.extend = function() {\r\n        // copy reference to target object\r\n        var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;\r\n\r\n        // Handle a deep copy situation\r\n        if ( typeof target === \"boolean\" ) {\r\n            deep = target;\r\n            target = arguments[1] || {};\r\n            // skip the boolean and the target\r\n            i = 2;\r\n        }\r\n\r\n        // Handle case when target is a string or something (possible in deep copy)\r\n        if ( typeof target !== \"object\" && !toString.call(target) === \"[object Function]\" ) {\r\n            target = {};\r\n        }\r\n\r\n        for ( ; i < length; i++ ){\r\n            // Only deal with non-null/undefined values\r\n            if ( (options = arguments[ i ]) != null ) {\r\n                // Extend the base object\r\n                for ( var name in options ) {\r\n                    var src = target[ name ], copy = options[ name ];\r\n\r\n                    // Prevent never-ending loop\r\n                    if ( target === copy ) {\r\n                        continue;\r\n                    }\r\n\r\n                    // Recurse if we're merging object values\r\n                    if ( deep && copy && typeof copy === \"object\" && !copy.nodeType ) {\r\n                        target[ name ] = $.jqplot.extend( deep, \r\n                            // Never move original objects, clone them\r\n                            src || ( copy.length != null ? [ ] : { } )\r\n                        , copy );\r\n                    }\r\n                    // Don't bring in undefined values\r\n                    else if ( copy !== undefined ) {\r\n                        target[ name ] = copy;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        // Return the modified object\r\n        return target;\r\n    };\r\n\r\n    /**\r\n     * method: rename\r\n     * \r\n     * Rename a theme.\r\n     * \r\n     * parameters:\r\n     * \r\n     * oldName - current name of the theme.\r\n     * newName - desired name of the theme.\r\n     * \r\n     * returns:\r\n     * \r\n     * new Theme object.\r\n     */\r\n    $.jqplot.ThemeEngine.prototype.rename = function (oldName, newName) {\r\n        if (oldName == 'Default' || newName == 'Default') {\r\n            throw new Error (\"jqplot.ThemeEngine Error: Cannot rename from/to Default\");\r\n        }\r\n        if (this.themes.hasOwnProperty(newName)) {\r\n            throw new Error (\"jqplot.ThemeEngine Error: New name already in use.\");\r\n        }\r\n        else if (this.themes.hasOwnProperty(oldName)) {\r\n            var th = this.copy (oldName, newName);\r\n            this.remove(oldName);\r\n            return th;\r\n        }\r\n        throw new Error(\"jqplot.ThemeEngine Error: Old name or new name invalid\");\r\n    };\r\n\r\n    /**\r\n     * method: copy\r\n     * \r\n     * Create a copy of an existing theme in the themeEngine, adding it the themeEngine.\r\n     * \r\n     * parameters:\r\n     * \r\n     * sourceName - name of the existing theme.\r\n     * targetName - name of the copy.\r\n     * obj - optional object of style parameter to apply to the new theme.\r\n     * \r\n     * returns:\r\n     * \r\n     * new Theme object.\r\n     */\r\n    $.jqplot.ThemeEngine.prototype.copy = function (sourceName, targetName, obj) {\r\n        if (targetName == 'Default') {\r\n            throw new Error (\"jqplot.ThemeEngine Error: Cannot copy over Default theme\");\r\n        }\r\n        if (!this.themes.hasOwnProperty(sourceName)) {\r\n            var s = \"jqplot.ThemeEngine Error: Source name invalid\";\r\n            throw new Error(s);\r\n        }\r\n        if (this.themes.hasOwnProperty(targetName)) {\r\n            var s = \"jqplot.ThemeEngine Error: Target name invalid\";\r\n            throw new Error(s);\r\n        }\r\n        else {\r\n            var th = clone(this.themes[sourceName]);\r\n            th._name = targetName;\r\n            $.jqplot.extend(true, th, obj);\r\n            this._add(th);\r\n            return th;\r\n        }\r\n    };\r\n    \r\n    \r\n    $.jqplot.Theme = function(name, obj) {\r\n        if (typeof(name) == 'object') {\r\n            obj = obj || name;\r\n            name = null;\r\n        }\r\n        name = name || Date.parse(new Date());\r\n        this._name = name;\r\n        this.target = {\r\n            backgroundColor: null\r\n        };\r\n        this.legend = {\r\n            textColor: null,\r\n            fontFamily: null,\r\n            fontSize: null,\r\n            border: null,\r\n            background: null\r\n        };\r\n        this.title = {\r\n            textColor: null,\r\n            fontFamily: null,\r\n            fontSize: null,\r\n            textAlign: null\r\n        };\r\n        this.seriesStyles = {};\r\n        this.series = [];\r\n        this.grid = {\r\n            drawGridlines: null,\r\n            gridLineColor: null,\r\n            gridLineWidth: null,\r\n            backgroundColor: null,\r\n            borderColor: null,\r\n            borderWidth: null,\r\n            shadow: null\r\n        };\r\n        this.axesStyles = {label:{}, ticks:{}};\r\n        this.axes = {};\r\n        if (typeof(obj) == 'string') {\r\n            this._name = obj;\r\n        }\r\n        else if(typeof(obj) == 'object') {\r\n            $.jqplot.extend(true, this, obj);\r\n        }\r\n    };\r\n    \r\n    var AxisProperties = function() {\r\n        this.borderColor = null;\r\n        this.borderWidth = null;\r\n        this.ticks = new AxisTicks();\r\n        this.label = new AxisLabel();\r\n    };\r\n    \r\n    var AxisTicks = function() {\r\n        this.show = null;\r\n        this.showGridline = null;\r\n        this.showLabel = null;\r\n        this.showMark = null;\r\n        this.size = null;\r\n        this.textColor = null;\r\n        this.whiteSpace = null;\r\n        this.fontSize = null;\r\n        this.fontFamily = null;\r\n    };\r\n    \r\n    var AxisLabel = function() {\r\n        this.textColor = null;\r\n        this.whiteSpace = null;\r\n        this.fontSize = null;\r\n        this.fontFamily = null;\r\n        this.fontWeight = null;\r\n    };\r\n    \r\n    var LineSeriesProperties = function() {\r\n        this.color=null;\r\n        this.lineWidth=null;\r\n        this.linePattern=null;\r\n        this.shadow=null;\r\n        this.fillColor=null;\r\n        this.showMarker=null;\r\n        this.markerOptions = new MarkerOptions();\r\n    };\r\n    \r\n    var MarkerOptions = function() {\r\n        this.show = null;\r\n        this.style = null;\r\n        this.lineWidth = null;\r\n        this.size = null;\r\n        this.color = null;\r\n        this.shadow = null;\r\n    };\r\n    \r\n    var BarSeriesProperties = function() {\r\n        this.color=null;\r\n        this.seriesColors=null;\r\n        this.lineWidth=null;\r\n        this.shadow=null;\r\n        this.barPadding=null;\r\n        this.barMargin=null;\r\n        this.barWidth=null;\r\n        this.highlightColors=null;\r\n    };\r\n    \r\n    var PieSeriesProperties = function() {\r\n        this.seriesColors=null;\r\n        this.padding=null;\r\n        this.sliceMargin=null;\r\n        this.fill=null;\r\n        this.shadow=null;\r\n        this.startAngle=null;\r\n        this.lineWidth=null;\r\n        this.highlightColors=null;\r\n    };\r\n    \r\n    var DonutSeriesProperties = function() {\r\n        this.seriesColors=null;\r\n        this.padding=null;\r\n        this.sliceMargin=null;\r\n        this.fill=null;\r\n        this.shadow=null;\r\n        this.startAngle=null;\r\n        this.lineWidth=null;\r\n        this.innerDiameter=null;\r\n        this.thickness=null;\r\n        this.ringMargin=null;\r\n        this.highlightColors=null;\r\n    };\r\n    \r\n    var FunnelSeriesProperties = function() {\r\n        this.color=null;\r\n        this.lineWidth=null;\r\n        this.shadow=null;\r\n        this.padding=null;\r\n        this.sectionMargin=null;\r\n        this.seriesColors=null;\r\n        this.highlightColors=null;\r\n    };\r\n    \r\n    var MeterSeriesProperties = function() {\r\n        this.padding=null;\r\n        this.backgroundColor=null;\r\n        this.ringColor=null;\r\n        this.tickColor=null;\r\n        this.ringWidth=null;\r\n        this.intervalColors=null;\r\n        this.intervalInnerRadius=null;\r\n        this.intervalOuterRadius=null;\r\n        this.hubRadius=null;\r\n        this.needleThickness=null;\r\n        this.needlePad=null;\r\n    };\r\n        \r\n\r\n\r\n\r\n    $.fn.jqplotChildText = function() {\r\n        return $(this).contents().filter(function() {\r\n            return this.nodeType == 3;  // Node.TEXT_NODE not defined in I7\r\n        }).text();\r\n    };\r\n\r\n    // Returns font style as abbreviation for \"font\" property.\r\n    $.fn.jqplotGetComputedFontStyle = function() {\r\n        var css = window.getComputedStyle ?  window.getComputedStyle(this[0], \"\") : this[0].currentStyle;\r\n        var attrs = css['font-style'] ? ['font-style', 'font-weight', 'font-size', 'font-family'] : ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily'];\r\n        var style = [];\r\n\r\n        for (var i=0 ; i < attrs.length; ++i) {\r\n            var attr = String(css[attrs[i]]);\r\n\r\n            if (attr && attr != 'normal') {\r\n                style.push(attr);\r\n            }\r\n        }\r\n        return style.join(' ');\r\n    };\r\n\r\n    /**\r\n     * Namespace: $.fn\r\n     * jQuery namespace to attach functions to jQuery elements.\r\n     *  \r\n     */\r\n\r\n    $.fn.jqplotToImageCanvas = function(options) {\r\n\r\n        options = options || {};\r\n        var x_offset = (options.x_offset == null) ? 0 : options.x_offset;\r\n        var y_offset = (options.y_offset == null) ? 0 : options.y_offset;\r\n        var backgroundColor = (options.backgroundColor == null) ? 'rgb(255,255,255)' : options.backgroundColor;\r\n\r\n        if ($(this).width() == 0 || $(this).height() == 0) {\r\n            return null;\r\n        }\r\n\r\n        // excanvas and hence IE < 9 do not support toDataURL and cannot export images.\r\n        if ($.jqplot.use_excanvas) {\r\n            return null;\r\n        }\r\n        \r\n        var newCanvas = document.createElement(\"canvas\");\r\n        var h = $(this).outerHeight(true);\r\n        var w = $(this).outerWidth(true);\r\n        var offs = $(this).offset();\r\n        var plotleft = offs.left;\r\n        var plottop = offs.top;\r\n        var transx = 0, transy = 0;\r\n\r\n        // have to check if any elements are hanging outside of plot area before rendering,\r\n        // since changing width of canvas will erase canvas.\r\n\r\n        var clses = ['jqplot-table-legend', 'jqplot-xaxis-tick', 'jqplot-x2axis-tick', 'jqplot-yaxis-tick', 'jqplot-y2axis-tick', 'jqplot-y3axis-tick', \r\n        'jqplot-y4axis-tick', 'jqplot-y5axis-tick', 'jqplot-y6axis-tick', 'jqplot-y7axis-tick', 'jqplot-y8axis-tick', 'jqplot-y9axis-tick',\r\n        'jqplot-xaxis-label', 'jqplot-x2axis-label', 'jqplot-yaxis-label', 'jqplot-y2axis-label', 'jqplot-y3axis-label', 'jqplot-y4axis-label', \r\n        'jqplot-y5axis-label', 'jqplot-y6axis-label', 'jqplot-y7axis-label', 'jqplot-y8axis-label', 'jqplot-y9axis-label' ];\r\n\r\n        var temptop, templeft, tempbottom, tempright;\r\n\r\n        for (var i = 0; i < clses.length; i++) {\r\n            $(this).find('.'+clses[i]).each(function() {\r\n                temptop = $(this).offset().top - plottop;\r\n                templeft = $(this).offset().left - plotleft;\r\n                tempright = templeft + $(this).outerWidth(true) + transx;\r\n                tempbottom = temptop + $(this).outerHeight(true) + transy;\r\n                if (templeft < -transx) {\r\n                    w = w - transx - templeft;\r\n                    transx = -templeft;\r\n                }\r\n                if (temptop < -transy) {\r\n                    h = h - transy - temptop;\r\n                    transy = - temptop;\r\n                }\r\n                if (tempright > w) {\r\n                    w = tempright;\r\n                }\r\n                if (tempbottom > h) {\r\n                    h =  tempbottom;\r\n                }\r\n            });\r\n        }\r\n\r\n        newCanvas.width = w + Number(x_offset);\r\n        newCanvas.height = h + Number(y_offset);\r\n\r\n        var newContext = newCanvas.getContext(\"2d\"); \r\n\r\n        newContext.save();\r\n        newContext.fillStyle = backgroundColor;\r\n        newContext.fillRect(0,0, newCanvas.width, newCanvas.height);\r\n        newContext.restore();\r\n\r\n        newContext.translate(transx, transy);\r\n        newContext.textAlign = 'left';\r\n        newContext.textBaseline = 'top';\r\n\r\n        function getLineheight(el) {\r\n            var lineheight = parseInt($(el).css('line-height'), 10);\r\n\r\n            if (isNaN(lineheight)) {\r\n                lineheight = parseInt($(el).css('font-size'), 10) * 1.2;\r\n            }\r\n            return lineheight;\r\n        }\r\n\r\n        function writeWrappedText (el, context, text, left, top, canvasWidth) {\r\n            var lineheight = getLineheight(el);\r\n            var tagwidth = $(el).innerWidth();\r\n            var tagheight = $(el).innerHeight();\r\n            var words = text.split(/\\s+/);\r\n            var wl = words.length;\r\n            var w = '';\r\n            var breaks = [];\r\n            var temptop = top;\r\n            var templeft = left;\r\n\r\n            for (var i=0; i<wl; i++) {\r\n                w += words[i];\r\n                if (context.measureText(w).width > tagwidth && w.length > words[i].length) {\r\n                    breaks.push(i);\r\n                    w = '';\r\n                    i--;\r\n                }   \r\n            }\r\n            if (breaks.length === 0) {\r\n                // center text if necessary\r\n                if ($(el).css('textAlign') === 'center') {\r\n                    templeft = left + (canvasWidth - context.measureText(w).width)/2  - transx;\r\n                }\r\n                context.fillText(text, templeft, top);\r\n            }\r\n            else {\r\n                w = words.slice(0, breaks[0]).join(' ');\r\n                // center text if necessary\r\n                if ($(el).css('textAlign') === 'center') {\r\n                    templeft = left + (canvasWidth - context.measureText(w).width)/2  - transx;\r\n                }\r\n                context.fillText(w, templeft, temptop);\r\n                temptop += lineheight;\r\n                for (var i=1, l=breaks.length; i<l; i++) {\r\n                    w = words.slice(breaks[i-1], breaks[i]).join(' ');\r\n                    // center text if necessary\r\n                    if ($(el).css('textAlign') === 'center') {\r\n                        templeft = left + (canvasWidth - context.measureText(w).width)/2  - transx;\r\n                    }\r\n                    context.fillText(w, templeft, temptop);\r\n                    temptop += lineheight;\r\n                }\r\n                w = words.slice(breaks[i-1], words.length).join(' ');\r\n                // center text if necessary\r\n                if ($(el).css('textAlign') === 'center') {\r\n                    templeft = left + (canvasWidth - context.measureText(w).width)/2  - transx;\r\n                }\r\n                context.fillText(w, templeft, temptop);\r\n            }\r\n\r\n        }\r\n\r\n        function _jqpToImage(el, x_offset, y_offset) {\r\n            var tagname = el.tagName.toLowerCase();\r\n            var p = $(el).position();\r\n            var css = window.getComputedStyle ?  window.getComputedStyle(el, \"\") : el.currentStyle; // for IE < 9\r\n            var left = x_offset + p.left + parseInt(css.marginLeft, 10) + parseInt(css.borderLeftWidth, 10) + parseInt(css.paddingLeft, 10);\r\n            var top = y_offset + p.top + parseInt(css.marginTop, 10) + parseInt(css.borderTopWidth, 10)+ parseInt(css.paddingTop, 10);\r\n            var w = newCanvas.width;\r\n            // var left = x_offset + p.left + $(el).css('marginLeft') + $(el).css('borderLeftWidth') \r\n\r\n            // somehow in here, for divs within divs, the width of the inner div should be used instead of the canvas.\r\n\r\n            if ((tagname == 'div' || tagname == 'span') && !$(el).hasClass('jqplot-highlighter-tooltip')) {\r\n                $(el).children().each(function() {\r\n                    _jqpToImage(this, left, top);\r\n                });\r\n                var text = $(el).jqplotChildText();\r\n\r\n                if (text) {\r\n                    newContext.font = $(el).jqplotGetComputedFontStyle();\r\n                    newContext.fillStyle = $(el).css('color');\r\n\r\n                    writeWrappedText(el, newContext, text, left, top, w);\r\n                }\r\n            }\r\n\r\n            // handle the standard table legend\r\n\r\n            else if (tagname === 'table' && $(el).hasClass('jqplot-table-legend')) {\r\n                newContext.strokeStyle = $(el).css('border-top-color');\r\n                newContext.fillStyle = $(el).css('background-color');\r\n                newContext.fillRect(left, top, $(el).innerWidth(), $(el).innerHeight());\r\n                if (parseInt($(el).css('border-top-width'), 10) > 0) {\r\n                    newContext.strokeRect(left, top, $(el).innerWidth(), $(el).innerHeight());\r\n                }\r\n\r\n                // find all the swatches\r\n                $(el).find('div.jqplot-table-legend-swatch-outline').each(function() {\r\n                    // get the first div and stroke it\r\n                    var elem = $(this);\r\n                    newContext.strokeStyle = elem.css('border-top-color');\r\n                    var l = left + elem.position().left;\r\n                    var t = top + elem.position().top;\r\n                    newContext.strokeRect(l, t, elem.innerWidth(), elem.innerHeight());\r\n\r\n                    // now fill the swatch\r\n                    \r\n                    l += parseInt(elem.css('padding-left'), 10);\r\n                    t += parseInt(elem.css('padding-top'), 10);\r\n                    var h = elem.innerHeight() - 2 * parseInt(elem.css('padding-top'), 10);\r\n                    var w = elem.innerWidth() - 2 * parseInt(elem.css('padding-left'), 10);\r\n\r\n                    var swatch = elem.children('div.jqplot-table-legend-swatch');\r\n                    newContext.fillStyle = swatch.css('background-color');\r\n                    newContext.fillRect(l, t, w, h);\r\n                });\r\n\r\n                // now add text\r\n\r\n                $(el).find('td.jqplot-table-legend-label').each(function(){\r\n                    var elem = $(this);\r\n                    var l = left + elem.position().left;\r\n                    var t = top + elem.position().top + parseInt(elem.css('padding-top'), 10);\r\n                    newContext.font = elem.jqplotGetComputedFontStyle();\r\n                    newContext.fillStyle = elem.css('color');\r\n                    writeWrappedText(elem, newContext, elem.text(), l, t, w);\r\n                });\r\n\r\n                var elem = null;\r\n            }\r\n\r\n            else if (tagname == 'canvas') {\r\n                newContext.drawImage(el, left, top);\r\n            }\r\n        }\r\n        $(this).children().each(function() {\r\n            _jqpToImage(this, x_offset, y_offset);\r\n        });\r\n        return newCanvas;\r\n    };\r\n\r\n    // return the raw image data string.\r\n    // Should work on canvas supporting browsers.\r\n    $.fn.jqplotToImageStr = function(options) {\r\n        var imgCanvas = $(this).jqplotToImageCanvas(options);\r\n        if (imgCanvas) {\r\n            return imgCanvas.toDataURL(\"image/png\");\r\n        }\r\n        else {\r\n            return null;\r\n        }\r\n    };\r\n\r\n    // return a DOM <img> element and return it.\r\n    // Should work on canvas supporting browsers.\r\n    $.fn.jqplotToImageElem = function(options) {\r\n        var elem = document.createElement(\"img\");\r\n        var str = $(this).jqplotToImageStr(options);\r\n        elem.src = str;\r\n        return elem;\r\n    };\r\n\r\n    // return a string for an <img> element and return it.\r\n    // Should work on canvas supporting browsers.\r\n    $.fn.jqplotToImageElemStr = function(options) {\r\n        var str = '<img src='+$(this).jqplotToImageStr(options)+' />';\r\n        return str;\r\n    };\r\n\r\n    // Not guaranteed to work, even on canvas supporting browsers due to \r\n    // limitations with location.href and browser support.\r\n    $.fn.jqplotSaveImage = function() {\r\n        var imgData = $(this).jqplotToImageStr({});\r\n        if (imgData) {\r\n            window.location.href = imgData.replace(\"image/png\", \"image/octet-stream\");\r\n        }\r\n\r\n    };\r\n\r\n    // Not guaranteed to work, even on canvas supporting browsers due to\r\n    // limitations with window.open and arbitrary data.\r\n    $.fn.jqplotViewImage = function() {\r\n        var imgStr = $(this).jqplotToImageElemStr({});\r\n        var imgData = $(this).jqplotToImageStr({});\r\n        if (imgStr) {\r\n            var w = window.open('');\r\n            w.document.open(\"image/png\");\r\n            w.document.write(imgStr);\r\n            w.document.close();\r\n            w = null;\r\n        }\r\n    };\r\n    \r\n\r\n\r\n\r\n    /** \r\n     * @description\r\n     * <p>Object with extended date parsing and formatting capabilities.\r\n     * This library borrows many concepts and ideas from the Date Instance \r\n     * Methods by Ken Snyder along with some parts of Ken's actual code.</p>\r\n     *\r\n     * <p>jsDate takes a different approach by not extending the built-in \r\n     * Date Object, improving date parsing, allowing for multiple formatting \r\n     * syntaxes and multiple and more easily expandable localization.</p>\r\n     * \r\n     * @author Chris Leonello\r\n     * @date #date#\r\n     * @version #VERSION#\r\n     * @copyright (c) 2010-2015 Chris Leonello\r\n     * jsDate is currently available for use in all personal or commercial projects \r\n     * under both the MIT and GPL version 2.0 licenses. This means that you can \r\n     * choose the license that best suits your project and use it accordingly.\r\n     * \r\n     * <p>Ken's original Date Instance Methods and copyright notice:</p>\r\n     * <pre>\r\n     * Ken Snyder (ken d snyder at gmail dot com)\r\n     * 2008-09-10\r\n     * version 2.0.2 (http://kendsnyder.com/sandbox/date/)     \r\n     * Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/)\r\n     * </pre>\r\n     * \r\n     * @class\r\n     * @name jsDate\r\n     * @param  {String | Number | Array | Date&nbsp;Object | Options&nbsp;Object} arguments Optional arguments, either a parsable date/time string,\r\n     * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds],\r\n     * a Date object, or an options object of form {syntax: \"perl\", date:some Date} where all options are optional.\r\n     */\r\n     \r\n    var jsDate = function () {\r\n    \r\n        this.syntax = jsDate.config.syntax;\r\n        this._type = \"jsDate\";\r\n        this.proxy = new Date();\r\n        this.options = {};\r\n        this.locale = jsDate.regional.getLocale();\r\n        this.formatString = '';\r\n        this.defaultCentury = jsDate.config.defaultCentury;\r\n\r\n        switch ( arguments.length ) {\r\n            case 0:\r\n                break;\r\n            case 1:\r\n                // other objects either won't have a _type property or,\r\n                // if they do, it shouldn't be set to \"jsDate\", so\r\n                // assume it is an options argument.\r\n                if (get_type(arguments[0]) == \"[object Object]\" && arguments[0]._type != \"jsDate\") {\r\n                    var opts = this.options = arguments[0];\r\n                    this.syntax = opts.syntax || this.syntax;\r\n                    this.defaultCentury = opts.defaultCentury || this.defaultCentury;\r\n                    this.proxy = jsDate.createDate(opts.date);\r\n                }\r\n                else {\r\n                    this.proxy = jsDate.createDate(arguments[0]);\r\n                }\r\n                break;\r\n            default:\r\n                var a = [];\r\n                for ( var i=0; i<arguments.length; i++ ) {\r\n                    a.push(arguments[i]);\r\n                }\r\n                // this should be the current date/time?\r\n                this.proxy = new Date();\r\n                this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) );\r\n                if ( a.slice(3).length ) {\r\n                    this.proxy.setHours.apply( this.proxy, a.slice(3) );\r\n                }\r\n                break;\r\n        }\r\n    };\r\n    \r\n    /**\r\n     * @namespace Configuration options that will be used as defaults for all instances on the page.\r\n     * @property {String} defaultLocale The default locale to use [en].\r\n     * @property {String} syntax The default syntax to use [perl].\r\n     * @property {Number} defaultCentury The default centry for 2 digit dates.\r\n     */\r\n    jsDate.config = {\r\n        defaultLocale: 'en',\r\n        syntax: 'perl',\r\n        defaultCentury: 1900\r\n    };\r\n        \r\n    /**\r\n     * Add an arbitrary amount to the currently stored date\r\n     * \r\n     * @param {Number} number      \r\n     * @param {String} unit\r\n     * @returns {jsDate}       \r\n     */\r\n     \r\n    jsDate.prototype.add = function(number, unit) {\r\n        var factor = multipliers[unit] || multipliers.day;\r\n        if (typeof factor == 'number') {\r\n            this.proxy.setTime(this.proxy.getTime() + (factor * number));\r\n        } else {\r\n            factor.add(this, number);\r\n        }\r\n        return this;\r\n    };\r\n        \r\n    /**\r\n     * Create a new jqplot.date object with the same date\r\n     * \r\n     * @returns {jsDate}\r\n     */  \r\n     \r\n    jsDate.prototype.clone = function() {\r\n            return new jsDate(this.proxy.getTime());\r\n    };\r\n\r\n    /**\r\n     * Get the UTC TimeZone Offset of this date in milliseconds.\r\n     *\r\n     * @returns {Number}\r\n     */\r\n\r\n    jsDate.prototype.getUtcOffset = function() {\r\n        return this.proxy.getTimezoneOffset() * 60000;\r\n    };\r\n\r\n    /**\r\n     * Find the difference between this jsDate and another date.\r\n     * \r\n     * @param {String| Number| Array| jsDate&nbsp;Object| Date&nbsp;Object} dateObj\r\n     * @param {String} unit\r\n     * @param {Boolean} allowDecimal\r\n     * @returns {Number} Number of units difference between dates.\r\n     */\r\n     \r\n    jsDate.prototype.diff = function(dateObj, unit, allowDecimal) {\r\n        // ensure we have a Date object\r\n        dateObj = new jsDate(dateObj);\r\n        if (dateObj === null) {\r\n            return null;\r\n        }\r\n        // get the multiplying factor integer or factor function\r\n        var factor = multipliers[unit] || multipliers.day;\r\n        if (typeof factor == 'number') {\r\n            // multiply\r\n            var unitDiff = (this.proxy.getTime() - dateObj.proxy.getTime()) / factor;\r\n        } else {\r\n            // run function\r\n            var unitDiff = factor.diff(this.proxy, dateObj.proxy);\r\n        }\r\n        // if decimals are not allowed, round toward zero\r\n        return (allowDecimal ? unitDiff : Math[unitDiff > 0 ? 'floor' : 'ceil'](unitDiff));          \r\n    };\r\n    \r\n    /**\r\n     * Get the abbreviated name of the current week day\r\n     * \r\n     * @returns {String}\r\n     */   \r\n     \r\n    jsDate.prototype.getAbbrDayName = function() {\r\n        return jsDate.regional[this.locale][\"dayNamesShort\"][this.proxy.getDay()];\r\n    };\r\n    \r\n    /**\r\n     * Get the abbreviated name of the current month\r\n     * \r\n     * @returns {String}\r\n     */\r\n     \r\n    jsDate.prototype.getAbbrMonthName = function() {\r\n        return jsDate.regional[this.locale][\"monthNamesShort\"][this.proxy.getMonth()];\r\n    };\r\n    \r\n    /**\r\n     * Get UPPER CASE AM or PM for the current time\r\n     * \r\n     * @returns {String}\r\n     */\r\n     \r\n    jsDate.prototype.getAMPM = function() {\r\n        return this.proxy.getHours() >= 12 ? 'PM' : 'AM';\r\n    };\r\n    \r\n    /**\r\n     * Get lower case am or pm for the current time\r\n     * \r\n     * @returns {String}\r\n     */\r\n     \r\n    jsDate.prototype.getAmPm = function() {\r\n        return this.proxy.getHours() >= 12 ? 'pm' : 'am';\r\n    };\r\n    \r\n    /**\r\n     * Get the century (19 for 20th Century)\r\n     *\r\n     * @returns {Integer} Century (19 for 20th century).\r\n     */\r\n    jsDate.prototype.getCentury = function() { \r\n        return parseInt(this.proxy.getFullYear()/100, 10);\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getDate = function() {\r\n        return this.proxy.getDate();\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getDay = function() {\r\n        return this.proxy.getDay();\r\n    };\r\n    \r\n    /**\r\n     * Get the Day of week 1 (Monday) thru 7 (Sunday)\r\n     * \r\n     * @returns {Integer} Day of week 1 (Monday) thru 7 (Sunday)\r\n     */\r\n    jsDate.prototype.getDayOfWeek = function() { \r\n        var dow = this.proxy.getDay(); \r\n        return dow===0?7:dow; \r\n    };\r\n    \r\n    /**\r\n     * Get the day of the year\r\n     * \r\n     * @returns {Integer} 1 - 366, day of the year\r\n     */\r\n    jsDate.prototype.getDayOfYear = function() {\r\n        var d = this.proxy;\r\n        var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT');\r\n        ms += d.getTimezoneOffset()*60000;\r\n        d = null;\r\n        return parseInt(ms/60000/60/24, 10)+1;\r\n    };\r\n    \r\n    /**\r\n     * Get the name of the current week day\r\n     * \r\n     * @returns {String}\r\n     */  \r\n     \r\n    jsDate.prototype.getDayName = function() {\r\n        return jsDate.regional[this.locale][\"dayNames\"][this.proxy.getDay()];\r\n    };\r\n    \r\n    /**\r\n     * Get the week number of the given year, starting with the first Sunday as the first week\r\n     * @returns {Integer} Week number (13 for the 13th full week of the year).\r\n     */\r\n    jsDate.prototype.getFullWeekOfYear = function() {\r\n        var d = this.proxy;\r\n        var doy = this.getDayOfYear();\r\n        var rdow = 6-d.getDay();\r\n        var woy = parseInt((doy+rdow)/7, 10);\r\n        return woy;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getFullYear = function() {\r\n        return this.proxy.getFullYear();\r\n    };\r\n    \r\n    /**\r\n     * Get the GMT offset in hours and minutes (e.g. +06:30)\r\n     * \r\n     * @returns {String}\r\n     */\r\n     \r\n    jsDate.prototype.getGmtOffset = function() {\r\n        // divide the minutes offset by 60\r\n        var hours = this.proxy.getTimezoneOffset() / 60;\r\n        // decide if we are ahead of or behind GMT\r\n        var prefix = hours < 0 ? '+' : '-';\r\n        // remove the negative sign if any\r\n        hours = Math.abs(hours);\r\n        // add the +/- to the padded number of hours to : to the padded minutes\r\n        return prefix + addZeros(Math.floor(hours), 2) + ':' + addZeros((hours % 1) * 60, 2);\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getHours = function() {\r\n        return this.proxy.getHours();\r\n    };\r\n    \r\n    /**\r\n     * Get the current hour on a 12-hour scheme\r\n     * \r\n     * @returns {Integer}\r\n     */\r\n     \r\n    jsDate.prototype.getHours12  = function() {\r\n        var hours = this.proxy.getHours();\r\n        return hours > 12 ? hours - 12 : (hours == 0 ? 12 : hours);\r\n    };\r\n    \r\n    \r\n    jsDate.prototype.getIsoWeek = function() {\r\n        var d = this.proxy;\r\n        var woy = this.getWeekOfYear();\r\n        var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay();\r\n        // First week is 01 and not 00 as in the case of %U and %W,\r\n        // so we add 1 to the final result except if day 1 of the year\r\n        // is a Monday (then %W returns 01).\r\n        // We also need to subtract 1 if the day 1 of the year is \r\n        // Friday-Sunday, so the resulting equation becomes:\r\n        var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1);\r\n        if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4)\r\n        {\r\n            idow = 1;\r\n        }\r\n        else if(idow === 0)\r\n        {\r\n            d = new jsDate(new Date('' + (d.getFullYear()-1) + '/12/31'));\r\n            idow = d.getIsoWeek();\r\n        }\r\n        d = null;\r\n        return idow;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getMilliseconds = function() {\r\n        return this.proxy.getMilliseconds();\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getMinutes = function() {\r\n        return this.proxy.getMinutes();\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getMonth = function() {\r\n        return this.proxy.getMonth();\r\n    };\r\n    \r\n    /**\r\n     * Get the name of the current month\r\n     * \r\n     * @returns {String}\r\n     */\r\n     \r\n    jsDate.prototype.getMonthName = function() {\r\n        return jsDate.regional[this.locale][\"monthNames\"][this.proxy.getMonth()];\r\n    };\r\n    \r\n    /**\r\n     * Get the number of the current month, 1-12\r\n     * \r\n     * @returns {Integer}\r\n     */\r\n     \r\n    jsDate.prototype.getMonthNumber = function() {\r\n        return this.proxy.getMonth() + 1;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getSeconds = function() {\r\n        return this.proxy.getSeconds();\r\n    };\r\n    \r\n    /**\r\n     * Return a proper two-digit year integer\r\n     * \r\n     * @returns {Integer}\r\n     */\r\n     \r\n    jsDate.prototype.getShortYear = function() {\r\n        return this.proxy.getYear() % 100;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getTime = function() {\r\n        return this.proxy.getTime();\r\n    };\r\n    \r\n    /**\r\n     * Get the timezone abbreviation\r\n     *\r\n     * @returns {String} Abbreviation for the timezone\r\n     */\r\n    jsDate.prototype.getTimezoneAbbr = function() {\r\n        return this.proxy.toString().replace(/^.*\\(([^)]+)\\)$/, '$1'); \r\n    };\r\n    \r\n    /**\r\n     * Get the browser-reported name for the current timezone (e.g. MDT, Mountain Daylight Time)\r\n     * \r\n     * @returns {String}\r\n     */\r\n    jsDate.prototype.getTimezoneName = function() {\r\n        var match = /(?:\\((.+)\\)$| ([A-Z]{3}) )/.exec(this.toString());\r\n        return match[1] || match[2] || 'GMT' + this.getGmtOffset();\r\n    }; \r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getTimezoneOffset = function() {\r\n        return this.proxy.getTimezoneOffset();\r\n    };\r\n    \r\n    \r\n    /**\r\n     * Get the week number of the given year, starting with the first Monday as the first week\r\n     * @returns {Integer} Week number (13 for the 13th week of the year).\r\n     */\r\n    jsDate.prototype.getWeekOfYear = function() {\r\n        var doy = this.getDayOfYear();\r\n        var rdow = 7 - this.getDayOfWeek();\r\n        var woy = parseInt((doy+rdow)/7, 10);\r\n        return woy;\r\n    };\r\n    \r\n    /**\r\n     * Get the current date as a Unix timestamp\r\n     * \r\n     * @returns {Integer}\r\n     */\r\n     \r\n    jsDate.prototype.getUnix = function() {\r\n        return Math.round(this.proxy.getTime() / 1000, 0);\r\n    }; \r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */\r\n    jsDate.prototype.getYear = function() {\r\n        return this.proxy.getYear();\r\n    };\r\n    \r\n    /**\r\n     * Return a date one day ahead (or any other unit)\r\n     * \r\n     * @param {String} unit Optional, year | month | day | week | hour | minute | second | millisecond\r\n     * @returns {jsDate}\r\n     */\r\n     \r\n    jsDate.prototype.next = function(unit) {\r\n        unit = unit || 'day';\r\n        return this.clone().add(1, unit);\r\n    };\r\n    \r\n    /**\r\n     * Set the jsDate instance to a new date.\r\n     *\r\n     * @param  {String | Number | Array | Date Object | jsDate Object | Options Object} arguments Optional arguments, \r\n     * either a parsable date/time string,\r\n     * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds],\r\n     * a Date object, jsDate Object or an options object of form {syntax: \"perl\", date:some Date} where all options are optional.\r\n     */\r\n    jsDate.prototype.set = function() {\r\n        switch ( arguments.length ) {\r\n            case 0:\r\n                this.proxy = new Date();\r\n                break;\r\n            case 1:\r\n                // other objects either won't have a _type property or,\r\n                // if they do, it shouldn't be set to \"jsDate\", so\r\n                // assume it is an options argument.\r\n                if (get_type(arguments[0]) == \"[object Object]\" && arguments[0]._type != \"jsDate\") {\r\n                    var opts = this.options = arguments[0];\r\n                    this.syntax = opts.syntax || this.syntax;\r\n                    this.defaultCentury = opts.defaultCentury || this.defaultCentury;\r\n                    this.proxy = jsDate.createDate(opts.date);\r\n                }\r\n                else {\r\n                    this.proxy = jsDate.createDate(arguments[0]);\r\n                }\r\n                break;\r\n            default:\r\n                var a = [];\r\n                for ( var i=0; i<arguments.length; i++ ) {\r\n                    a.push(arguments[i]);\r\n                }\r\n                // this should be the current date/time\r\n                this.proxy = new Date();\r\n                this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) );\r\n                if ( a.slice(3).length ) {\r\n                    this.proxy.setHours.apply( this.proxy, a.slice(3) );\r\n                }\r\n                break;\r\n        }\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Sets the day of the month for a specified date according to local time.\r\n     * @param {Integer} dayValue An integer from 1 to 31, representing the day of the month. \r\n     */\r\n    jsDate.prototype.setDate = function(n) {\r\n        this.proxy.setDate(n);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Sets the full year for a specified date according to local time.\r\n     * @param {Integer} yearValue The numeric value of the year, for example, 1995.  \r\n     * @param {Integer} monthValue Optional, between 0 and 11 representing the months January through December.  \r\n     * @param {Integer} dayValue Optional, between 1 and 31 representing the day of the month. If you specify the dayValue parameter, you must also specify the monthValue. \r\n     */\r\n    jsDate.prototype.setFullYear = function() {\r\n        this.proxy.setFullYear.apply(this.proxy, arguments);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Sets the hours for a specified date according to local time.\r\n     * \r\n     * @param {Integer} hoursValue An integer between 0 and 23, representing the hour.  \r\n     * @param {Integer} minutesValue Optional, An integer between 0 and 59, representing the minutes.  \r\n     * @param {Integer} secondsValue Optional, An integer between 0 and 59, representing the seconds. \r\n     * If you specify the secondsValue parameter, you must also specify the minutesValue.  \r\n     * @param {Integer} msValue Optional, A number between 0 and 999, representing the milliseconds. \r\n     * If you specify the msValue parameter, you must also specify the minutesValue and secondsValue. \r\n     */\r\n    jsDate.prototype.setHours = function() {\r\n        this.proxy.setHours.apply(this.proxy, arguments);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */ \r\n    jsDate.prototype.setMilliseconds = function(n) {\r\n        this.proxy.setMilliseconds(n);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */ \r\n    jsDate.prototype.setMinutes = function() {\r\n        this.proxy.setMinutes.apply(this.proxy, arguments);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */ \r\n    jsDate.prototype.setMonth = function() {\r\n        this.proxy.setMonth.apply(this.proxy, arguments);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */ \r\n    jsDate.prototype.setSeconds = function() {\r\n        this.proxy.setSeconds.apply(this.proxy, arguments);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */ \r\n    jsDate.prototype.setTime = function(n) {\r\n        this.proxy.setTime(n);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Implements Date functionality\r\n     */ \r\n    jsDate.prototype.setYear = function() {\r\n        this.proxy.setYear.apply(this.proxy, arguments);\r\n        return this;\r\n    };\r\n    \r\n    /**\r\n     * Provide a formatted string representation of this date.\r\n     * \r\n     * @param {String} formatString A format string.  \r\n     * See: {@link jsDate.formats}.\r\n     * @returns {String} Date String.\r\n     */\r\n            \r\n    jsDate.prototype.strftime = function(formatString) {\r\n        formatString = formatString || this.formatString || jsDate.regional[this.locale]['formatString'];\r\n        return jsDate.strftime(this, formatString, this.syntax);\r\n    };\r\n        \r\n    /**\r\n     * Return a String representation of this jsDate object.\r\n     * @returns {String} Date string.\r\n     */\r\n    \r\n    jsDate.prototype.toString = function() {\r\n        return this.proxy.toString();\r\n    };\r\n        \r\n    /**\r\n     * Convert the current date to an 8-digit integer (%Y%m%d)\r\n     * \r\n     * @returns {Integer}\r\n     */\r\n     \r\n    jsDate.prototype.toYmdInt = function() {\r\n        return (this.proxy.getFullYear() * 10000) + (this.getMonthNumber() * 100) + this.proxy.getDate();\r\n    };\r\n    \r\n    /**\r\n     * @namespace Holds localizations for month/day names.\r\n     * <p>jsDate attempts to detect locale when loaded and defaults to 'en'.\r\n     * If a localization is detected which is not available, jsDate defaults to 'en'.\r\n     * Additional localizations can be added after jsDate loads.  After adding a localization,\r\n     * call the jsDate.regional.getLocale() method.  Currently, en, fr and de are defined.</p>\r\n     * \r\n     * <p>Localizations must be an object and have the following properties defined:  monthNames, monthNamesShort, dayNames, dayNamesShort and Localizations are added like:</p>\r\n     * <pre class=\"code\">\r\n     * jsDate.regional['en'] = {\r\n     * monthNames      : 'January February March April May June July August September October November December'.split(' '),\r\n     * monthNamesShort : 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '),\r\n     * dayNames        : 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '),\r\n     * dayNamesShort   : 'Sun Mon Tue Wed Thu Fri Sat'.split(' ')\r\n     * };\r\n     * </pre>\r\n     * <p>After adding localizations, call <code>jsDate.regional.getLocale();</code> to update the locale setting with the\r\n     * new localizations.</p>\r\n     */\r\n     \r\n    jsDate.regional = {\r\n        'en': {\r\n            monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],\r\n            monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],\r\n            dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],\r\n            dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n        \r\n        'fr': {\r\n            monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'],\r\n            monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'],\r\n            dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],\r\n            dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n        \r\n        'de': {\r\n            monthNames: ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'],\r\n            monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'],\r\n            dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],\r\n            dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n        \r\n        'es': {\r\n            monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],\r\n            monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun', 'Jul','Ago','Sep','Oct','Nov','Dic'],\r\n            dayNames: ['Domingo','Lunes','Martes','Mi&eacute;rcoles','Jueves','Viernes','S&aacute;bado'],\r\n            dayNamesShort: ['Dom','Lun','Mar','Mi&eacute;','Juv','Vie','S&aacute;b'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n        \r\n        'ru': {\r\n            monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],\r\n            monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн','Июл','Авг','Сен','Окт','Ноя','Дек'],\r\n            dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],\r\n            dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n        \r\n        'ar': {\r\n            monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران','تموز', 'آب', 'أيلول',   'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],\r\n            monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],\r\n            dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'],\r\n            dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n        \r\n        'pt': {\r\n            monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],\r\n            monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'],\r\n            dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],\r\n            dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'   \r\n        },\r\n        \r\n        'pt-BR': {\r\n            monthNames: ['Janeiro','Fevereiro','Mar&ccedil;o','Abril','Maio','Junho', 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],\r\n            monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'],\r\n            dayNames: ['Domingo','Segunda-feira','Ter&ccedil;a-feira','Quarta-feira','Quinta-feira','Sexta-feira','S&aacute;bado'],\r\n            dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','S&aacute;b'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n        \r\n        'pl': {\r\n            monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec','Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],\r\n            monthNamesShort: ['Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze','Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'],\r\n            dayNames: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'],\r\n            dayNamesShort: ['Ni', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'Sb'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n\r\n        'nl': {\r\n            monthNames: ['Januari','Februari','Maart','April','Mei','Juni','July','Augustus','September','Oktober','November','December'],\r\n            monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Aug','Sep','Okt','Nov','Dec'],\r\n            dayNames:','['Zondag','Maandag','Dinsdag','Woensdag','Donderdag','Vrijdag','Zaterdag'],\r\n            dayNamesShort: ['Zo','Ma','Di','Wo','Do','Vr','Za'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n\r\n        'sv': {\r\n            monthNames: ['januari','februari','mars','april','maj','juni','juli','augusti','september','oktober','november','december'],\r\n            monthNamesShort: ['jan','feb','mar','apr','maj','jun','jul','aug','sep','okt','nov','dec'],\r\n            dayNames: ['söndag','måndag','tisdag','onsdag','torsdag','fredag','lördag'],\r\n            dayNamesShort: ['sön','mån','tis','ons','tor','fre','lör'],\r\n            formatString: '%Y-%m-%d %H:%M:%S'\r\n        },\r\n\r\n        'it': {\r\n            monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],\r\n            monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'],\r\n            dayNames: ['Domenica','Lunedi','Martedi','Mercoledi','Giovedi','Venerdi','Sabato'],\r\n            dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],\r\n            formatString: '%d-%m-%Y %H:%M:%S'\r\n        }\r\n    \r\n    };\r\n    \r\n    // Set english variants to 'en'\r\n    jsDate.regional['en-US'] = jsDate.regional['en-GB'] = jsDate.regional['en'];\r\n    \r\n    /**\r\n     * Try to determine the users locale based on the lang attribute of the html page.  Defaults to 'en'\r\n     * if it cannot figure out a locale of if the locale does not have a localization defined.\r\n     * @returns {String} locale\r\n     */\r\n     \r\n    jsDate.regional.getLocale = function () {\r\n        var l = jsDate.config.defaultLocale;\r\n        \r\n        if ( document && document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang ) {\r\n            l = document.getElementsByTagName('html')[0].lang;\r\n            if (!jsDate.regional.hasOwnProperty(l)) {\r\n                l = jsDate.config.defaultLocale;\r\n            }\r\n        }\r\n        \r\n        return l;\r\n    };\r\n    \r\n    // ms in day\r\n    var day = 24 * 60 * 60 * 1000;\r\n    \r\n    // padd a number with zeros\r\n    var addZeros = function(num, digits) {\r\n        num = String(num);\r\n        var i = digits - num.length;\r\n        var s = String(Math.pow(10, i)).slice(1);\r\n        return s.concat(num);\r\n    };\r\n\r\n    // representations used for calculating differences between dates.\r\n    // This borrows heavily from Ken Snyder's work.\r\n    var multipliers = {\r\n        millisecond: 1,\r\n        second: 1000,\r\n        minute: 60 * 1000,\r\n        hour: 60 * 60 * 1000,\r\n        day: day,\r\n        week: 7 * day,\r\n        month: {\r\n            // add a number of months\r\n            add: function(d, number) {\r\n                // add any years needed (increments of 12)\r\n                multipliers.year.add(d, Math[number > 0 ? 'floor' : 'ceil'](number / 12));\r\n                // ensure that we properly wrap betwen December and January\r\n                // 11 % 12 = 11\r\n                // 12 % 12 = 0\r\n                var prevMonth = d.getMonth() + (number % 12);\r\n                if (prevMonth == 12) {\r\n                    prevMonth = 0;\r\n                    d.setYear(d.getFullYear() + 1);\r\n                } else if (prevMonth == -1) {\r\n                    prevMonth = 11;\r\n                    d.setYear(d.getFullYear() - 1);\r\n                }\r\n                d.setMonth(prevMonth);\r\n            },\r\n            // get the number of months between two Date objects (decimal to the nearest day)\r\n            diff: function(d1, d2) {\r\n                // get the number of years\r\n                var diffYears = d1.getFullYear() - d2.getFullYear();\r\n                // get the number of remaining months\r\n                var diffMonths = d1.getMonth() - d2.getMonth() + (diffYears * 12);\r\n                // get the number of remaining days\r\n                var diffDays = d1.getDate() - d2.getDate();\r\n                // return the month difference with the days difference as a decimal\r\n                return diffMonths + (diffDays / 30);\r\n            }\r\n        },\r\n        year: {\r\n            // add a number of years\r\n            add: function(d, number) {\r\n                d.setYear(d.getFullYear() + Math[number > 0 ? 'floor' : 'ceil'](number));\r\n            },\r\n            // get the number of years between two Date objects (decimal to the nearest day)\r\n            diff: function(d1, d2) {\r\n                return multipliers.month.diff(d1, d2) / 12;\r\n            }\r\n        }        \r\n    };\r\n    //\r\n    // Alias each multiplier with an 's' to allow 'year' and 'years' for example.\r\n    // This comes from Ken Snyders work.\r\n    //\r\n    for (var unit in multipliers) {\r\n        if (unit.substring(unit.length - 1) != 's') { // IE will iterate newly added properties :|\r\n            multipliers[unit + 's'] = multipliers[unit];\r\n        }\r\n    }\r\n    \r\n    //\r\n    // take a jsDate instance and a format code and return the formatted value.\r\n    // This is a somewhat modified version of Ken Snyder's method.\r\n    //\r\n    var format = function(d, code, syntax) {\r\n        // if shorcut codes are used, recursively expand those.\r\n        if (jsDate.formats[syntax][\"shortcuts\"][code]) {\r\n            return jsDate.strftime(d, jsDate.formats[syntax][\"shortcuts\"][code], syntax);\r\n        } else {\r\n            // get the format code function and addZeros() argument\r\n            var getter = (jsDate.formats[syntax][\"codes\"][code] || '').split('.');\r\n            var nbr = d['get' + getter[0]] ? d['get' + getter[0]]() : '';\r\n            if (getter[1]) {\r\n                nbr = addZeros(nbr, getter[1]);\r\n            }\r\n            return nbr;\r\n        }       \r\n    };\r\n    \r\n    /**\r\n     * @static\r\n     * Static function for convert a date to a string according to a given format.  Also acts as namespace for strftime format codes.\r\n     * <p>strftime formatting can be accomplished without creating a jsDate object by calling jsDate.strftime():</p>\r\n     * <pre class=\"code\">\r\n     * var formattedDate = jsDate.strftime('Feb 8, 2006 8:48:32', '%Y-%m-%d %H:%M:%S');\r\n     * </pre>\r\n     * @param {String | Number | Array | jsDate&nbsp;Object | Date&nbsp;Object} date A parsable date string, JavaScript time stamp, Array of form [year, month, day, hours, minutes, seconds, milliseconds], jsDate Object or Date object.\r\n     * @param {String} formatString String with embedded date formatting codes.  \r\n     * See: {@link jsDate.formats}. \r\n     * @param {String} syntax Optional syntax to use [default perl].\r\n     * @param {String} locale Optional locale to use.\r\n     * @returns {String} Formatted representation of the date.\r\n    */\r\n    //\r\n    // Logic as implemented here is very similar to Ken Snyder's Date Instance Methods.\r\n    //\r\n    jsDate.strftime = function(d, formatString, syntax, locale) {\r\n        var syn = 'perl';\r\n        var loc = jsDate.regional.getLocale();\r\n        \r\n        // check if syntax and locale are available or reversed\r\n        if (syntax && jsDate.formats.hasOwnProperty(syntax)) {\r\n            syn = syntax;\r\n        }\r\n        else if (syntax && jsDate.regional.hasOwnProperty(syntax)) {\r\n            loc = syntax;\r\n        }\r\n        \r\n        if (locale && jsDate.formats.hasOwnProperty(locale)) {\r\n            syn = locale;\r\n        }\r\n        else if (locale && jsDate.regional.hasOwnProperty(locale)) {\r\n            loc = locale;\r\n        }\r\n        \r\n        if (get_type(d) != \"[object Object]\" || d._type != \"jsDate\") {\r\n            d = new jsDate(d);\r\n            d.locale = loc;\r\n        }\r\n        if (!formatString) {\r\n            formatString = d.formatString || jsDate.regional[loc]['formatString'];\r\n        }\r\n        // default the format string to year-month-day\r\n        var source = formatString || '%Y-%m-%d', \r\n            result = '', \r\n            match;\r\n        // replace each format code\r\n        while (source.length > 0) {\r\n            if (match = source.match(jsDate.formats[syn].codes.matcher)) {\r\n                result += source.slice(0, match.index);\r\n                result += (match[1] || '') + format(d, match[2], syn);\r\n                source = source.slice(match.index + match[0].length);\r\n            } else {\r\n                result += source;\r\n                source = '';\r\n            }\r\n        }\r\n        return result;\r\n    };\r\n    \r\n    /**\r\n     * @namespace\r\n     * Namespace to hold format codes and format shortcuts.  \"perl\" and \"php\" format codes \r\n     * and shortcuts are defined by default.  Additional codes and shortcuts can be\r\n     * added like:\r\n     * \r\n     * <pre class=\"code\">\r\n     * jsDate.formats[\"perl\"] = {\r\n     *     \"codes\": {\r\n     *         matcher: /someregex/,\r\n     *         Y: \"fullYear\",  // name of \"get\" method without the \"get\",\r\n     *         ...,            // more codes\r\n     *     },\r\n     *     \"shortcuts\": {\r\n     *         F: '%Y-%m-%d',\r\n     *         ...,            // more shortcuts\r\n     *     }\r\n     * };\r\n     * </pre>\r\n     * \r\n     * <p>Additionally, ISO and SQL shortcuts are defined and can be accesses via:\r\n     * <code>jsDate.formats.ISO</code> and <code>jsDate.formats.SQL</code>\r\n     */\r\n    \r\n    jsDate.formats = {\r\n        ISO:'%Y-%m-%dT%H:%M:%S.%N%G',\r\n        SQL:'%Y-%m-%d %H:%M:%S'\r\n    };\r\n    \r\n    /**\r\n     * Perl format codes and shortcuts for strftime.\r\n     * \r\n     * A hash (object) of codes where each code must be an array where the first member is \r\n     * the name of a Date.prototype or jsDate.prototype function to call\r\n     * and optionally a second member indicating the number to pass to addZeros()\r\n     * \r\n     * <p>The following format codes are defined:</p>\r\n     * \r\n     * <pre class=\"code\">\r\n     * Code    Result                    Description\r\n     * == Years ==           \r\n     * %Y      2008                      Four-digit year\r\n     * %y      08                        Two-digit year\r\n     * \r\n     * == Months ==          \r\n     * %m      09                        Two-digit month\r\n     * %#m     9                         One or two-digit month\r\n     * %B      September                 Full month name\r\n     * %b      Sep                       Abbreviated month name\r\n     * \r\n     * == Days ==            \r\n     * %d      05                        Two-digit day of month\r\n     * %#d     5                         One or two-digit day of month\r\n     * %e      5                         One or two-digit day of month\r\n     * %A      Sunday                    Full name of the day of the week\r\n     * %a      Sun                       Abbreviated name of the day of the week\r\n     * %w      0                         Number of the day of the week (0 = Sunday, 6 = Saturday)\r\n     * \r\n     * == Hours ==           \r\n     * %H      23                        Hours in 24-hour format (two digits)\r\n     * %#H     3                         Hours in 24-hour integer format (one or two digits)\r\n     * %I      11                        Hours in 12-hour format (two digits)\r\n     * %#I     3                         Hours in 12-hour integer format (one or two digits)\r\n     * %p      PM                        AM or PM\r\n     * \r\n     * == Minutes ==         \r\n     * %M      09                        Minutes (two digits)\r\n     * %#M     9                         Minutes (one or two digits)\r\n     * \r\n     * == Seconds ==         \r\n     * %S      02                        Seconds (two digits)\r\n     * %#S     2                         Seconds (one or two digits)\r\n     * %s      1206567625723             Unix timestamp (Seconds past 1970-01-01 00:00:00)\r\n     * \r\n     * == Milliseconds ==    \r\n     * %N      008                       Milliseconds (three digits)\r\n     * %#N     8                         Milliseconds (one to three digits)\r\n     * \r\n     * == Timezone ==        \r\n     * %O      360                       difference in minutes between local time and GMT\r\n     * %Z      Mountain Standard Time    Name of timezone as reported by browser\r\n     * %G      06:00                     Hours and minutes between GMT\r\n     * \r\n     * == Shortcuts ==       \r\n     * %F      2008-03-26                %Y-%m-%d\r\n     * %T      05:06:30                  %H:%M:%S\r\n     * %X      05:06:30                  %H:%M:%S\r\n     * %x      03/26/08                  %m/%d/%y\r\n     * %D      03/26/08                  %m/%d/%y\r\n     * %#c     Wed Mar 26 15:31:00 2008  %a %b %e %H:%M:%S %Y\r\n     * %v      3-Sep-2008                %e-%b-%Y\r\n     * %R      15:31                     %H:%M\r\n     * %r      03:31:00 PM               %I:%M:%S %p\r\n     * \r\n     * == Characters ==      \r\n     * %n      \\n                        Newline\r\n     * %t      \\t                        Tab\r\n     * %%      %                         Percent Symbol\r\n     * </pre>\r\n     * \r\n     * <p>Formatting shortcuts that will be translated into their longer version.\r\n     * Be sure that format shortcuts do not refer to themselves: this will cause an infinite loop.</p>\r\n     * \r\n     * <p>Format codes and format shortcuts can be redefined after the jsDate\r\n     * module is imported.</p>\r\n     * \r\n     * <p>Note that if you redefine the whole hash (object), you must supply a \"matcher\"\r\n     * regex for the parser.  The default matcher is:</p>\r\n     * \r\n     * <code>/()%(#?(%|[a-z]))/i</code>\r\n     * \r\n     * <p>which corresponds to the Perl syntax used by default.</p>\r\n     * \r\n     * <p>By customizing the matcher and format codes, nearly any strftime functionality is possible.</p>\r\n     */\r\n     \r\n    jsDate.formats.perl = {\r\n        codes: {\r\n            //\r\n            // 2-part regex matcher for format codes\r\n            //\r\n            // first match must be the character before the code (to account for escaping)\r\n            // second match must be the format code character(s)\r\n            //\r\n            matcher: /()%(#?(%|[a-z]))/i,\r\n            // year\r\n            Y: 'FullYear',\r\n            y: 'ShortYear.2',\r\n            // month\r\n            m: 'MonthNumber.2',\r\n            '#m': 'MonthNumber',\r\n            B: 'MonthName',\r\n            b: 'AbbrMonthName',\r\n            // day\r\n            d: 'Date.2',\r\n            '#d': 'Date',\r\n            e: 'Date',\r\n            A: 'DayName',\r\n            a: 'AbbrDayName',\r\n            w: 'Day',\r\n            // hours\r\n            H: 'Hours.2',\r\n            '#H': 'Hours',\r\n            I: 'Hours12.2',\r\n            '#I': 'Hours12',\r\n            p: 'AMPM',\r\n            // minutes\r\n            M: 'Minutes.2',\r\n            '#M': 'Minutes',\r\n            // seconds\r\n            S: 'Seconds.2',\r\n            '#S': 'Seconds',\r\n            s: 'Unix',\r\n            // milliseconds\r\n            N: 'Milliseconds.3',\r\n            '#N': 'Milliseconds',\r\n            // timezone\r\n            O: 'TimezoneOffset',\r\n            Z: 'TimezoneName',\r\n            G: 'GmtOffset'  \r\n        },\r\n        \r\n        shortcuts: {\r\n            // date\r\n            F: '%Y-%m-%d',\r\n            // time\r\n            T: '%H:%M:%S',\r\n            X: '%H:%M:%S',\r\n            // local format date\r\n            x: '%m/%d/%y',\r\n            D: '%m/%d/%y',\r\n            // local format extended\r\n            '#c': '%a %b %e %H:%M:%S %Y',\r\n            // local format short\r\n            v: '%e-%b-%Y',\r\n            R: '%H:%M',\r\n            r: '%I:%M:%S %p',\r\n            // tab and newline\r\n            t: '\\t',\r\n            n: '\\n',\r\n            '%': '%'\r\n        }\r\n    };\r\n    \r\n    /**\r\n     * PHP format codes and shortcuts for strftime.\r\n     * \r\n     * A hash (object) of codes where each code must be an array where the first member is \r\n     * the name of a Date.prototype or jsDate.prototype function to call\r\n     * and optionally a second member indicating the number to pass to addZeros()\r\n     * \r\n     * <p>The following format codes are defined:</p>\r\n     * \r\n     * <pre class=\"code\">\r\n     * Code    Result                    Description\r\n     * === Days ===        \r\n     * %a      Sun through Sat           An abbreviated textual representation of the day\r\n     * %A      Sunday - Saturday         A full textual representation of the day\r\n     * %d      01 to 31                  Two-digit day of the month (with leading zeros)\r\n     * %e      1 to 31                   Day of the month, with a space preceding single digits.\r\n     * %j      001 to 366                Day of the year, 3 digits with leading zeros\r\n     * %u      1 - 7 (Mon - Sun)         ISO-8601 numeric representation of the day of the week\r\n     * %w      0 - 6 (Sun - Sat)         Numeric representation of the day of the week\r\n     *                                  \r\n     * === Week ===                     \r\n     * %U      13                        Full Week number, starting with the first Sunday as the first week\r\n     * %V      01 through 53             ISO-8601:1988 week number, starting with the first week of the year \r\n     *                                   with at least 4 weekdays, with Monday being the start of the week\r\n     * %W      46                        A numeric representation of the week of the year, \r\n     *                                   starting with the first Monday as the first week\r\n     * === Month ===                    \r\n     * %b      Jan through Dec           Abbreviated month name, based on the locale\r\n     * %B      January - December        Full month name, based on the locale\r\n     * %h      Jan through Dec           Abbreviated month name, based on the locale (an alias of %b)\r\n     * %m      01 - 12 (Jan - Dec)       Two digit representation of the month\r\n     * \r\n     * === Year ===                     \r\n     * %C      19                        Two digit century (year/100, truncated to an integer)\r\n     * %y      09 for 2009               Two digit year\r\n     * %Y      2038                      Four digit year\r\n     * \r\n     * === Time ===                     \r\n     * %H      00 through 23             Two digit representation of the hour in 24-hour format\r\n     * %I      01 through 12             Two digit representation of the hour in 12-hour format\r\n     * %l      1 through 12              Hour in 12-hour format, with a space preceeding single digits\r\n     * %M      00 through 59             Two digit representation of the minute\r\n     * %p      AM/PM                     UPPER-CASE 'AM' or 'PM' based on the given time\r\n     * %P      am/pm                     lower-case 'am' or 'pm' based on the given time\r\n     * %r      09:34:17 PM               Same as %I:%M:%S %p\r\n     * %R      00:35                     Same as %H:%M\r\n     * %S      00 through 59             Two digit representation of the second\r\n     * %T      21:34:17                  Same as %H:%M:%S\r\n     * %X      03:59:16                  Preferred time representation based on locale, without the date\r\n     * %z      -0500 or EST              Either the time zone offset from UTC or the abbreviation\r\n     * %Z      -0500 or EST              The time zone offset/abbreviation option NOT given by %z\r\n     * \r\n     * === Time and Date ===            \r\n     * %D      02/05/09                  Same as %m/%d/%y\r\n     * %F      2009-02-05                Same as %Y-%m-%d (commonly used in database datestamps)\r\n     * %s      305815200                 Unix Epoch Time timestamp (same as the time() function)\r\n     * %x      02/05/09                  Preferred date representation, without the time\r\n     * \r\n     * === Miscellaneous ===            \r\n     * %n        ---                     A newline character (\\n)\r\n     * %t        ---                     A Tab character (\\t)\r\n     * %%        ---                     A literal percentage character (%)\r\n     * </pre>\r\n     */\r\n \r\n    jsDate.formats.php = {\r\n        codes: {\r\n            //\r\n            // 2-part regex matcher for format codes\r\n            //\r\n            // first match must be the character before the code (to account for escaping)\r\n            // second match must be the format code character(s)\r\n            //\r\n            matcher: /()%((%|[a-z]))/i,\r\n            // day\r\n            a: 'AbbrDayName',\r\n            A: 'DayName',\r\n            d: 'Date.2',\r\n            e: 'Date',\r\n            j: 'DayOfYear.3',\r\n            u: 'DayOfWeek',\r\n            w: 'Day',\r\n            // week\r\n            U: 'FullWeekOfYear.2',\r\n            V: 'IsoWeek.2',\r\n            W: 'WeekOfYear.2',\r\n            // month\r\n            b: 'AbbrMonthName',\r\n            B: 'MonthName',\r\n            m: 'MonthNumber.2',\r\n            h: 'AbbrMonthName',\r\n            // year\r\n            C: 'Century.2',\r\n            y: 'ShortYear.2',\r\n            Y: 'FullYear',\r\n            // time\r\n            H: 'Hours.2',\r\n            I: 'Hours12.2',\r\n            l: 'Hours12',\r\n            p: 'AMPM',\r\n            P: 'AmPm',\r\n            M: 'Minutes.2',\r\n            S: 'Seconds.2',\r\n            s: 'Unix',\r\n            O: 'TimezoneOffset',\r\n            z: 'GmtOffset',\r\n            Z: 'TimezoneAbbr'\r\n        },\r\n        \r\n        shortcuts: {\r\n            D: '%m/%d/%y',\r\n            F: '%Y-%m-%d',\r\n            T: '%H:%M:%S',\r\n            X: '%H:%M:%S',\r\n            x: '%m/%d/%y',\r\n            R: '%H:%M',\r\n            r: '%I:%M:%S %p',\r\n            t: '\\t',\r\n            n: '\\n',\r\n            '%': '%'\r\n        }\r\n    };   \r\n    //\r\n    // Conceptually, the logic implemented here is similar to Ken Snyder's Date Instance Methods.\r\n    // I use his idea of a set of parsers which can be regular expressions or functions,\r\n    // iterating through those, and then seeing if Date.parse() will create a date.\r\n    // The parser expressions and functions are a little different and some bugs have been\r\n    // worked out.  Also, a lot of \"pre-parsing\" is done to fix implementation\r\n    // variations of Date.parse() between browsers.\r\n    //\r\n    jsDate.createDate = function(date) {\r\n        // if passing in multiple arguments, try Date constructor\r\n        if (date == null) {\r\n            return new Date();\r\n        }\r\n        // If the passed value is already a date object, return it\r\n        if (date instanceof Date) {\r\n            return date;\r\n        }\r\n        // if (typeof date == 'number') return new Date(date * 1000);\r\n        // If the passed value is an integer, interpret it as a javascript timestamp\r\n        if (typeof date == 'number') {\r\n            return new Date(date);\r\n        }\r\n        \r\n        // Before passing strings into Date.parse(), have to normalize them for certain conditions.\r\n        // If strings are not formatted staccording to the EcmaScript spec, results from Date parse will be implementation dependent.  \r\n        // \r\n        // For example: \r\n        //  * FF and Opera assume 2 digit dates are pre y2k, Chome assumes <50 is pre y2k, 50+ is 21st century.  \r\n        //  * Chrome will correctly parse '1984-1-25' into localtime, FF and Opera will not parse.\r\n        //  * Both FF, Chrome and Opera will parse '1984/1/25' into localtime.\r\n        \r\n        // remove leading and trailing spaces\r\n        var parsable = String(date).replace(/^\\s*(.+)\\s*$/g, '$1');\r\n        \r\n        // replace dahses (-) with slashes (/) in dates like n[nnn]/n[n]/n[nnn]\r\n        parsable = parsable.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/, \"$1/$2/$3\");\r\n        \r\n        /////////\r\n        // Need to check for '15-Dec-09' also.\r\n        // FF will not parse, but Chrome will.\r\n        // Chrome will set date to 2009 as well.\r\n        /////////\r\n        \r\n        // first check for 'dd-mmm-yyyy' or 'dd/mmm/yyyy' like '15-Dec-2010'\r\n        parsable = parsable.replace(/^(3[01]|[0-2]?\\d)[-\\/]([a-z]{3,})[-\\/](\\d{4})/i, \"$1 $2 $3\");\r\n        \r\n        // Now check for 'dd-mmm-yy' or 'dd/mmm/yy' and normalize years to default century.\r\n        var match = parsable.match(/^(3[01]|[0-2]?\\d)[-\\/]([a-z]{3,})[-\\/](\\d{2})\\D*/i);\r\n        if (match && match.length > 3) {\r\n            var m3 = parseFloat(match[3]);\r\n            var ny = jsDate.config.defaultCentury + m3;\r\n            ny = String(ny);\r\n            \r\n            // now replace 2 digit year with 4 digit year\r\n            parsable = parsable.replace(/^(3[01]|[0-2]?\\d)[-\\/]([a-z]{3,})[-\\/](\\d{2})\\D*/i, match[1] +' '+ match[2] +' '+ ny);\r\n            \r\n        }\r\n        \r\n        // Check for '1/19/70 8:14PM'\r\n        // where starts with mm/dd/yy or yy/mm/dd and have something after\r\n        // Check if 1st postiion is greater than 31, assume it is year.\r\n        // Assme all 2 digit years are 1900's.\r\n        // Finally, change them into US style mm/dd/yyyy representations.\r\n        match = parsable.match(/^([0-9]{1,2})[-\\/]([0-9]{1,2})[-\\/]([0-9]{1,2})[^0-9]/);\r\n        \r\n        function h1(parsable, match) {\r\n            var m1 = parseFloat(match[1]);\r\n            var m2 = parseFloat(match[2]);\r\n            var m3 = parseFloat(match[3]);\r\n            var cent = jsDate.config.defaultCentury;\r\n            var ny, nd, nm, str;\r\n            \r\n            if (m1 > 31) { // first number is a year\r\n                nd = m3;\r\n                nm = m2;\r\n                ny = cent + m1;\r\n            }\r\n            \r\n            else { // last number is the year\r\n                nd = m2;\r\n                nm = m1;\r\n                ny = cent + m3;\r\n            }\r\n            \r\n            str = nm+'/'+nd+'/'+ny;\r\n            \r\n            // now replace 2 digit year with 4 digit year\r\n            return  parsable.replace(/^([0-9]{1,2})[-\\/]([0-9]{1,2})[-\\/]([0-9]{1,2})/, str);\r\n        \r\n        }\r\n        \r\n        if (match && match.length > 3) {\r\n            parsable = h1(parsable, match);\r\n        }\r\n        \r\n        // Now check for '1/19/70' with nothing after and do as above\r\n        var match = parsable.match(/^([0-9]{1,2})[-\\/]([0-9]{1,2})[-\\/]([0-9]{1,2})$/);\r\n        \r\n        if (match && match.length > 3) {\r\n            parsable = h1(parsable, match);\r\n        }\r\n                \r\n        \r\n        var i = 0;\r\n        var length = jsDate.matchers.length;\r\n        var pattern,\r\n            ms,\r\n            current = parsable,\r\n            obj;\r\n        while (i < length) {\r\n            ms = Date.parse(current);\r\n            if (!isNaN(ms)) {\r\n                return new Date(ms);\r\n            }\r\n            pattern = jsDate.matchers[i];\r\n            if (typeof pattern == 'function') {\r\n                obj = pattern.call(jsDate, current);\r\n                if (obj instanceof Date) {\r\n                    return obj;\r\n                }\r\n            } else {\r\n                current = parsable.replace(pattern[0], pattern[1]);\r\n            }\r\n            i++;\r\n        }\r\n        return NaN;\r\n    };\r\n    \r\n\r\n    /**\r\n     * @static\r\n     * Handy static utility function to return the number of days in a given month.\r\n     * @param {Integer} year Year\r\n     * @param {Integer} month Month (1-12)\r\n     * @returns {Integer} Number of days in the month.\r\n    */\r\n    //\r\n    // handy utility method Borrowed right from Ken Snyder's Date Instance Mehtods.\r\n    // \r\n    jsDate.daysInMonth = function(year, month) {\r\n        if (month == 2) {\r\n            return new Date(year, 1, 29).getDate() == 29 ? 29 : 28;\r\n        }\r\n        return [undefined,31,undefined,31,30,31,30,31,31,30,31,30,31][month];\r\n    };\r\n\r\n\r\n    //\r\n    // An Array of regular expressions or functions that will attempt to match the date string.\r\n    // Functions are called with scope of a jsDate instance.\r\n    //\r\n    jsDate.matchers = [\r\n        // convert dd.mmm.yyyy to mm/dd/yyyy (world date to US date).\r\n        [/(3[01]|[0-2]\\d)\\s*\\.\\s*(1[0-2]|0\\d)\\s*\\.\\s*([1-9]\\d{3})/, '$2/$1/$3'],\r\n        // convert yyyy-mm-dd to mm/dd/yyyy (ISO date to US date).\r\n        [/([1-9]\\d{3})\\s*-\\s*(1[0-2]|0\\d)\\s*-\\s*(3[01]|[0-2]\\d)/, '$2/$3/$1'],\r\n        // Handle 12 hour or 24 hour time with milliseconds am/pm and optional date part.\r\n        function(str) { \r\n            var match = str.match(/^(?:(.+)\\s+)?([012]?\\d)(?:\\s*\\:\\s*(\\d\\d))?(?:\\s*\\:\\s*(\\d\\d(\\.\\d*)?))?\\s*(am|pm)?\\s*$/i);\r\n            //                   opt. date      hour       opt. minute     opt. second       opt. msec   opt. am or pm\r\n            if (match) {\r\n                if (match[1]) {\r\n                    var d = this.createDate(match[1]);\r\n                    if (isNaN(d)) {\r\n                        return;\r\n                    }\r\n                } else {\r\n                    var d = new Date();\r\n                    d.setMilliseconds(0);\r\n                }\r\n                var hour = parseFloat(match[2]);\r\n                if (match[6]) {\r\n                    hour = match[6].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12);\r\n                }\r\n                d.setHours(hour, parseInt(match[3] || 0, 10), parseInt(match[4] || 0, 10), ((parseFloat(match[5] || 0)) || 0)*1000);\r\n                return d;\r\n            }\r\n            else {\r\n                return str;\r\n            }\r\n        },\r\n        // Handle ISO timestamp with time zone.\r\n        function(str) {\r\n            var match = str.match(/^(?:(.+))[T|\\s+]([012]\\d)(?:\\:(\\d\\d))(?:\\:(\\d\\d))(?:\\.\\d+)([\\+\\-]\\d\\d\\:\\d\\d)$/i);\r\n            if (match) {\r\n                if (match[1]) {\r\n                    var d = this.createDate(match[1]);\r\n                    if (isNaN(d)) {\r\n                        return;\r\n                    }\r\n                } else {\r\n                    var d = new Date();\r\n                    d.setMilliseconds(0);\r\n                }\r\n                var hour = parseFloat(match[2]);\r\n                d.setHours(hour, parseInt(match[3], 10), parseInt(match[4], 10), parseFloat(match[5])*1000);\r\n                return d;\r\n            }\r\n            else {\r\n                    return str;\r\n            }\r\n        },\r\n        // Try to match ambiguous strings like 12/8/22.\r\n        // Use FF date assumption that 2 digit years are 20th century (i.e. 1900's).\r\n        // This may be redundant with pre processing of date already performed.\r\n        function(str) {\r\n            var match = str.match(/^([0-3]?\\d)\\s*[-\\/.\\s]{1}\\s*([a-zA-Z]{3,9})\\s*[-\\/.\\s]{1}\\s*([0-3]?\\d)$/);\r\n            if (match) {\r\n                var d = new Date();\r\n                var cent = jsDate.config.defaultCentury;\r\n                var m1 = parseFloat(match[1]);\r\n                var m3 = parseFloat(match[3]);\r\n                var ny, nd, nm;\r\n                if (m1 > 31) { // first number is a year\r\n                    nd = m3;\r\n                    ny = cent + m1;\r\n                }\r\n                \r\n                else { // last number is the year\r\n                    nd = m1;\r\n                    ny = cent + m3;\r\n                }\r\n                \r\n                var nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()][\"monthNamesShort\"]);\r\n                \r\n                if (nm == -1) {\r\n                    nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()][\"monthNames\"]);\r\n                }\r\n            \r\n                d.setFullYear(ny, nm, nd);\r\n                d.setHours(0,0,0,0);\r\n                return d;\r\n            }\r\n            \r\n            else {\r\n                return str;\r\n            }\r\n        }      \r\n    ];\r\n\r\n    //\r\n    // I think John Reisig published this method on his blog, ejohn.\r\n    //\r\n    function inArray( elem, array ) {\r\n        if ( array.indexOf ) {\r\n            return array.indexOf( elem );\r\n        }\r\n\r\n        for ( var i = 0, length = array.length; i < length; i++ ) {\r\n            if ( array[ i ] === elem ) {\r\n                return i;\r\n            }\r\n        }\r\n\r\n        return -1;\r\n    }\r\n    \r\n    //\r\n    // Thanks to Kangax, Christian Sciberras and Stack Overflow for this method.\r\n    //\r\n    function get_type(thing){\r\n        if(thing===null) return \"[object Null]\"; // special case\r\n        return Object.prototype.toString.call(thing);\r\n    }\r\n    \r\n    $.jsDate = jsDate;\r\n\r\n      \r\n    /**\r\n     * JavaScript printf/sprintf functions.\r\n     * \r\n     * This code has been adapted from the publicly available sprintf methods\r\n     * by Ash Searle. His original header follows:\r\n     *\r\n     *     This code is unrestricted: you are free to use it however you like.\r\n     *     \r\n     *     The functions should work as expected, performing left or right alignment,\r\n     *     truncating strings, outputting numbers with a required precision etc.\r\n     *\r\n     *     For complex cases, these functions follow the Perl implementations of\r\n     *     (s)printf, allowing arguments to be passed out-of-order, and to set the\r\n     *     precision or length of the output based on arguments instead of fixed\r\n     *     numbers.\r\n     *\r\n     *     See http://perldoc.perl.org/functions/sprintf.html for more information.\r\n     *\r\n     *     Implemented:\r\n     *     - zero and space-padding\r\n     *     - right and left-alignment,\r\n     *     - base X prefix (binary, octal and hex)\r\n     *     - positive number prefix\r\n     *     - (minimum) width\r\n     *     - precision / truncation / maximum width\r\n     *     - out of order arguments\r\n     *\r\n     *     Not implemented (yet):\r\n     *     - vector flag\r\n     *     - size (bytes, words, long-words etc.)\r\n     *     \r\n     *     Will not implement:\r\n     *     - %n or %p (no pass-by-reference in JavaScript)\r\n     *\r\n     *     @version 2007.04.27\r\n     *     @author Ash Searle \r\n     * \r\n     * You can see the original work and comments on his blog:\r\n     * http://hexmen.com/blog/2007/03/printf-sprintf/\r\n     * http://hexmen.com/js/sprintf.js\r\n     */\r\n     \r\n     /**\r\n      * @Modifications 2009.05.26\r\n      * @author Chris Leonello\r\n      * \r\n      * Added %p %P specifier\r\n      * Acts like %g or %G but will not add more significant digits to the output than present in the input.\r\n      * Example:\r\n      * Format: '%.3p', Input: 0.012, Output: 0.012\r\n      * Format: '%.3g', Input: 0.012, Output: 0.0120\r\n      * Format: '%.4p', Input: 12.0, Output: 12.0\r\n      * Format: '%.4g', Input: 12.0, Output: 12.00\r\n      * Format: '%.4p', Input: 4.321e-5, Output: 4.321e-5\r\n      * Format: '%.4g', Input: 4.321e-5, Output: 4.3210e-5\r\n      * \r\n      * Example:\r\n      * >>> $.jqplot.sprintf('%.2f, %d', 23.3452, 43.23)\r\n      * \"23.35, 43\"\r\n      * >>> $.jqplot.sprintf(\"no value: %n, decimal with thousands separator: %'d\", 23.3452, 433524)\r\n      * \"no value: , decimal with thousands separator: 433,524\"\r\n      */\r\n    $.jqplot.sprintf = function() {\r\n        function pad(str, len, chr, leftJustify) {\r\n            var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);\r\n            return leftJustify ? str + padding : padding + str;\r\n\r\n        }\r\n\r\n        function thousand_separate(value) {\r\n            var value_str = new String(value);\r\n            for (var i=10; i>0; i--) {\r\n                if (value_str == (value_str = value_str.replace(/^(\\d+)(\\d{3})/, \"$1\"+$.jqplot.sprintf.thousandsSeparator+\"$2\"))) break;\r\n            }\r\n            return value_str; \r\n        }\r\n\r\n        function justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace) {\r\n            var diff = minWidth - value.length;\r\n            if (diff > 0) {\r\n                var spchar = ' ';\r\n                if (htmlSpace) { spchar = '&nbsp;'; }\r\n                if (leftJustify || !zeroPad) {\r\n                    value = pad(value, minWidth, spchar, leftJustify);\r\n                } else {\r\n                    value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);\r\n                }\r\n            }\r\n            return value;\r\n        }\r\n\r\n        function formatBaseX(value, base, prefix, leftJustify, minWidth, precision, zeroPad, htmlSpace) {\r\n            // Note: casts negative numbers to positive ones\r\n            var number = value >>> 0;\r\n            prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';\r\n            value = prefix + pad(number.toString(base), precision || 0, '0', false);\r\n            return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace);\r\n        }\r\n\r\n        function formatString(value, leftJustify, minWidth, precision, zeroPad, htmlSpace) {\r\n            if (precision != null) {\r\n                value = value.slice(0, precision);\r\n            }\r\n            return justify(value, '', leftJustify, minWidth, zeroPad, htmlSpace);\r\n        }\r\n\r\n        var a = arguments, i = 0, format = a[i++];\r\n\r\n        return format.replace($.jqplot.sprintf.regex, function(substring, valueIndex, flags, minWidth, _, precision, type) {\r\n            if (substring == '%%') { return '%'; }\r\n\r\n            // parse flags\r\n            var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, htmlSpace = false, thousandSeparation = false;\r\n            for (var j = 0; flags && j < flags.length; j++) switch (flags.charAt(j)) {\r\n                case ' ': positivePrefix = ' '; break;\r\n                case '+': positivePrefix = '+'; break;\r\n                case '-': leftJustify = true; break;\r\n                case '0': zeroPad = true; break;\r\n                case '#': prefixBaseX = true; break;\r\n                case '&': htmlSpace = true; break;\r\n                case '\\'': thousandSeparation = true; break;\r\n            }\r\n\r\n            // parameters may be null, undefined, empty-string or real valued\r\n            // we want to ignore null, undefined and empty-string values\r\n\r\n            if (!minWidth) {\r\n                minWidth = 0;\r\n            } \r\n            else if (minWidth == '*') {\r\n                minWidth = +a[i++];\r\n            } \r\n            else if (minWidth.charAt(0) == '*') {\r\n                minWidth = +a[minWidth.slice(1, -1)];\r\n            } \r\n            else {\r\n                minWidth = +minWidth;\r\n            }\r\n\r\n            // Note: undocumented perl feature:\r\n            if (minWidth < 0) {\r\n                minWidth = -minWidth;\r\n                leftJustify = true;\r\n            }\r\n\r\n            if (!isFinite(minWidth)) {\r\n                throw new Error('$.jqplot.sprintf: (minimum-)width must be finite');\r\n            }\r\n\r\n            if (!precision) {\r\n                precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0);\r\n            } \r\n            else if (precision == '*') {\r\n                precision = +a[i++];\r\n            } \r\n            else if (precision.charAt(0) == '*') {\r\n                precision = +a[precision.slice(1, -1)];\r\n            } \r\n            else {\r\n                precision = +precision;\r\n            }\r\n\r\n            // grab value using valueIndex if required?\r\n            var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];\r\n\r\n            switch (type) {\r\n            case 's': {\r\n                if (value == null) {\r\n                    return '';\r\n                }\r\n                return formatString(String(value), leftJustify, minWidth, precision, zeroPad, htmlSpace);\r\n            }\r\n            case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad, htmlSpace);\r\n            case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad,htmlSpace);\r\n            case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace);\r\n            case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace);\r\n            case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace).toUpperCase();\r\n            case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace);\r\n            case 'i': {\r\n              var number = parseInt(+value, 10);\r\n              if (isNaN(number)) {\r\n                return '';\r\n              }\r\n              var prefix = number < 0 ? '-' : positivePrefix;\r\n              var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number));\r\n              value = prefix + pad(number_str, precision, '0', false);\r\n              //value = prefix + pad(String(Math.abs(number)), precision, '0', false);\r\n              return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace);\r\n                  }\r\n            case 'd': {\r\n              var number = Math.round(+value);\r\n              if (isNaN(number)) {\r\n                return '';\r\n              }\r\n              var prefix = number < 0 ? '-' : positivePrefix;\r\n              var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number));\r\n              value = prefix + pad(number_str, precision, '0', false);\r\n              return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace);\r\n                  }\r\n            case 'e':\r\n            case 'E':\r\n            case 'f':\r\n            case 'F':\r\n            case 'g':\r\n            case 'G':\r\n                      {\r\n                      var number = +value;\r\n                      if (isNaN(number)) {\r\n                          return '';\r\n                      }\r\n                      var prefix = number < 0 ? '-' : positivePrefix;\r\n                      var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];\r\n                      var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];\r\n                      var number_str = Math.abs(number)[method](precision);\r\n                      \r\n                      // Apply the decimal mark properly by splitting the number by the\r\n                      //   decimalMark, applying thousands separator, and then placing it\r\n                      //   back in.\r\n                      var parts = number_str.toString().split('.');\r\n                      parts[0] = thousandSeparation ? thousand_separate(parts[0]) : parts[0];\r\n                      number_str = parts.join($.jqplot.sprintf.decimalMark);\r\n                      \r\n                      value = prefix + number_str;\r\n                      var justified = justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform]();\r\n                      \r\n                      return justified;\r\n                  }\r\n            case 'p':\r\n            case 'P':\r\n            {\r\n                // make sure number is a number\r\n                var number = +value;\r\n                if (isNaN(number)) {\r\n                    return '';\r\n                }\r\n                var prefix = number < 0 ? '-' : positivePrefix;\r\n\r\n                var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/);\r\n                var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : String(number).length;\r\n                var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0;\r\n                \r\n                if (Math.abs(number) < 1) {\r\n                    if (sd + zeros  <= precision) {\r\n                        value = prefix + Math.abs(number).toPrecision(sd);\r\n                    }\r\n                    else {\r\n                        if (sd  <= precision - 1) {\r\n                            value = prefix + Math.abs(number).toExponential(sd-1);\r\n                        }\r\n                        else {\r\n                            value = prefix + Math.abs(number).toExponential(precision-1);\r\n                        }\r\n                    }\r\n                }\r\n                else {\r\n                    var prec = (sd <= precision) ? sd : precision;\r\n                    value = prefix + Math.abs(number).toPrecision(prec);\r\n                }\r\n                var textTransform = ['toString', 'toUpperCase']['pP'.indexOf(type) % 2];\r\n                return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform]();\r\n            }\r\n            case 'n': return '';\r\n            default: return substring;\r\n            }\r\n        });\r\n    };\r\n\r\n    $.jqplot.sprintf.thousandsSeparator = ',';\r\n    // Specifies the decimal mark for floating point values. By default a period '.'\r\n    // is used. If you change this value to for example a comma be sure to also\r\n    // change the thousands separator or else this won't work since a simple String\r\n    // replace is used (replacing all periods with the mark specified here).\r\n    $.jqplot.sprintf.decimalMark = '.';\r\n    \r\n    $.jqplot.sprintf.regex = /%%|%(\\d+\\$)?([-+#0&\\' ]*)(\\*\\d+\\$|\\*|\\d+)?(\\.(\\*\\d+\\$|\\*|\\d+))?([nAscboxXuidfegpEGP])/g;\r\n\r\n    $.jqplot.getSignificantFigures = function(number) {\r\n        var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/);\r\n        // total significant digits\r\n        var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length;\r\n        var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0;\r\n        // exponent\r\n        var expn = parseInt(parts[1], 10);\r\n        // digits to the left of the decimal place\r\n        var dleft = (expn + 1 > 0) ? expn + 1 : 0;\r\n        // digits to the right of the decimal place\r\n        var dright = (sd <= dleft) ? 0 : sd - expn - 1;\r\n        return {significantDigits: sd, digitsLeft: dleft, digitsRight: dright, zeros: zeros, exponent: expn} ;\r\n    };\r\n\r\n    $.jqplot.getPrecision = function(number) {\r\n        return $.jqplot.getSignificantFigures(number).digitsRight;\r\n    };\r\n\r\n  \r\n\r\n\r\n    var backCompat = $.uiBackCompat !== false;\r\n\r\n    $.jqplot.effects = {\r\n        effect: {}\r\n    };\r\n\r\n    // prefix used for storing data on .data()\r\n    var dataSpace = \"jqplot.storage.\";\r\n\r\n    /******************************************************************************/\r\n    /*********************************** EFFECTS **********************************/\r\n    /******************************************************************************/\r\n\r\n    $.extend( $.jqplot.effects, {\r\n        version: \"1.9pre\",\r\n\r\n        // Saves a set of properties in a data storage\r\n        save: function( element, set ) {\r\n            for( var i=0; i < set.length; i++ ) {\r\n                if ( set[ i ] !== null ) {\r\n                    element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );\r\n                }\r\n            }\r\n        },\r\n\r\n        // Restores a set of previously saved properties from a data storage\r\n        restore: function( element, set ) {\r\n            for( var i=0; i < set.length; i++ ) {\r\n                if ( set[ i ] !== null ) {\r\n                    element.css( set[ i ], element.data( dataSpace + set[ i ] ) );\r\n                }\r\n            }\r\n        },\r\n\r\n        setMode: function( el, mode ) {\r\n            if (mode === \"toggle\") {\r\n                mode = el.is( \":hidden\" ) ? \"show\" : \"hide\";\r\n            }\r\n            return mode;\r\n        },\r\n\r\n        // Wraps the element around a wrapper that copies position properties\r\n        createWrapper: function( element ) {\r\n\r\n            // if the element is already wrapped, return it\r\n            if ( element.parent().is( \".ui-effects-wrapper\" )) {\r\n                return element.parent();\r\n            }\r\n\r\n            // wrap the element\r\n            var props = {\r\n                    width: element.outerWidth(true),\r\n                    height: element.outerHeight(true),\r\n                    \"float\": element.css( \"float\" )\r\n                },\r\n                wrapper = $( \"<div></div>\" )\r\n                    .addClass( \"ui-effects-wrapper\" )\r\n                    .css({\r\n                        fontSize: \"100%\",\r\n                        background: \"transparent\",\r\n                        border: \"none\",\r\n                        margin: 0,\r\n                        padding: 0\r\n                    }),\r\n                // Store the size in case width/height are defined in % - Fixes #5245\r\n                size = {\r\n                    width: element.width(),\r\n                    height: element.height()\r\n                },\r\n                active = document.activeElement;\r\n\r\n            element.wrap( wrapper );\r\n\r\n            // Fixes #7595 - Elements lose focus when wrapped.\r\n            if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\r\n                $( active ).focus();\r\n            }\r\n\r\n            wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element\r\n\r\n            // transfer positioning properties to the wrapper\r\n            if ( element.css( \"position\" ) === \"static\" ) {\r\n                wrapper.css({ position: \"relative\" });\r\n                element.css({ position: \"relative\" });\r\n            } else {\r\n                $.extend( props, {\r\n                    position: element.css( \"position\" ),\r\n                    zIndex: element.css( \"z-index\" )\r\n                });\r\n                $.each([ \"top\", \"left\", \"bottom\", \"right\" ], function(i, pos) {\r\n                    props[ pos ] = element.css( pos );\r\n                    if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {\r\n                        props[ pos ] = \"auto\";\r\n                    }\r\n                });\r\n                element.css({\r\n                    position: \"relative\",\r\n                    top: 0,\r\n                    left: 0,\r\n                    right: \"auto\",\r\n                    bottom: \"auto\"\r\n                });\r\n            }\r\n            element.css(size);\r\n\r\n            return wrapper.css( props ).show();\r\n        },\r\n\r\n        removeWrapper: function( element ) {\r\n            var active = document.activeElement;\r\n\r\n            if ( element.parent().is( \".ui-effects-wrapper\" ) ) {\r\n                element.parent().replaceWith( element );\r\n\r\n                // Fixes #7595 - Elements lose focus when wrapped.\r\n                if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\r\n                    $( active ).focus();\r\n                }\r\n            }\r\n\r\n\r\n            return element;\r\n        }\r\n    });\r\n\r\n    // return an effect options object for the given parameters:\r\n    function _normalizeArguments( effect, options, speed, callback ) {\r\n\r\n        // short path for passing an effect options object:\r\n        if ( $.isPlainObject( effect ) ) {\r\n            return effect;\r\n        }\r\n\r\n        // convert to an object\r\n        effect = { effect: effect };\r\n\r\n        // catch (effect)\r\n        if ( options === undefined ) {\r\n            options = {};\r\n        }\r\n\r\n        // catch (effect, callback)\r\n        if ( $.isFunction( options ) ) {\r\n            callback = options;\r\n            speed = null;\r\n            options = {};\r\n        }\r\n\r\n        // catch (effect, speed, ?)\r\n        if ( $.type( options ) === \"number\" || $.fx.speeds[ options ]) {\r\n            callback = speed;\r\n            speed = options;\r\n            options = {};\r\n        }\r\n\r\n        // catch (effect, options, callback)\r\n        if ( $.isFunction( speed ) ) {\r\n            callback = speed;\r\n            speed = null;\r\n        }\r\n\r\n        // add options to effect\r\n        if ( options ) {\r\n            $.extend( effect, options );\r\n        }\r\n\r\n        speed = speed || options.duration;\r\n        effect.duration = $.fx.off ? 0 : typeof speed === \"number\"\r\n            ? speed : speed in $.fx.speeds ? $.fx.speeds[ speed ] : $.fx.speeds._default;\r\n\r\n        effect.complete = callback || options.complete;\r\n\r\n        return effect;\r\n    }\r\n\r\n    function standardSpeed( speed ) {\r\n        // valid standard speeds\r\n        if ( !speed || typeof speed === \"number\" || $.fx.speeds[ speed ] ) {\r\n            return true;\r\n        }\r\n\r\n        // invalid strings - treat as \"normal\" speed\r\n        if ( typeof speed === \"string\" && !$.jqplot.effects.effect[ speed ] ) {\r\n            // TODO: remove in 2.0 (#7115)\r\n            if ( backCompat && $.jqplot.effects[ speed ] ) {\r\n                return false;\r\n            }\r\n            return true;\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    $.fn.extend({\r\n        jqplotEffect: function( effect, options, speed, callback ) {\r\n            var args = _normalizeArguments.apply( this, arguments ),\r\n                mode = args.mode,\r\n                queue = args.queue,\r\n                effectMethod = $.jqplot.effects.effect[ args.effect ],\r\n\r\n                // DEPRECATED: remove in 2.0 (#7115)\r\n                oldEffectMethod = !effectMethod && backCompat && $.jqplot.effects[ args.effect ];\r\n\r\n            if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) {\r\n                // delegate to the original method (e.g., .show()) if possible\r\n                if ( mode ) {\r\n                    return this[ mode ]( args.duration, args.complete );\r\n                } else {\r\n                    return this.each( function() {\r\n                        if ( args.complete ) {\r\n                            args.complete.call( this );\r\n                        }\r\n                    });\r\n                }\r\n            }\r\n\r\n            function run( next ) {\r\n                var elem = $( this ),\r\n                    complete = args.complete,\r\n                    mode = args.mode;\r\n\r\n                function done() {\r\n                    if ( $.isFunction( complete ) ) {\r\n                        complete.call( elem[0] );\r\n                    }\r\n                    if ( $.isFunction( next ) ) {\r\n                        next();\r\n                    }\r\n                }\r\n\r\n                // if the element is hiddden and mode is hide,\r\n                // or element is visible and mode is show\r\n                if ( elem.is( \":hidden\" ) ? mode === \"hide\" : mode === \"show\" ) {\r\n                    done();\r\n                } else {\r\n                    effectMethod.call( elem[0], args, done );\r\n                }\r\n            }\r\n\r\n            // TODO: remove this check in 2.0, effectMethod will always be true\r\n            if ( effectMethod ) {\r\n                return queue === false ? this.each( run ) : this.queue( queue || \"fx\", run );\r\n            } else {\r\n                // DEPRECATED: remove in 2.0 (#7115)\r\n                return oldEffectMethod.call(this, {\r\n                    options: args,\r\n                    duration: args.duration,\r\n                    callback: args.complete,\r\n                    mode: args.mode\r\n                });\r\n            }\r\n        }\r\n    });\r\n\r\n\r\n\r\n\r\n    var rvertical = /up|down|vertical/,\r\n        rpositivemotion = /up|left|vertical|horizontal/;\r\n\r\n    $.jqplot.effects.effect.blind = function( o, done ) {\r\n        // Create element\r\n        var el = $( this ),\r\n            props = [ \"position\", \"top\", \"bottom\", \"left\", \"right\", \"height\", \"width\" ],\r\n            mode = $.jqplot.effects.setMode( el, o.mode || \"hide\" ),\r\n            direction = o.direction || \"up\",\r\n            vertical = rvertical.test( direction ),\r\n            ref = vertical ? \"height\" : \"width\",\r\n            ref2 = vertical ? \"top\" : \"left\",\r\n            motion = rpositivemotion.test( direction ),\r\n            animation = {},\r\n            show = mode === \"show\",\r\n            wrapper, distance, top;\r\n\r\n        // // if already wrapped, the wrapper's properties are my property. #6245\r\n        if ( el.parent().is( \".ui-effects-wrapper\" ) ) {\r\n            $.jqplot.effects.save( el.parent(), props );\r\n        } else {\r\n            $.jqplot.effects.save( el, props );\r\n        }\r\n        el.show();\r\n        top = parseInt(el.css('top'), 10);\r\n        wrapper = $.jqplot.effects.createWrapper( el ).css({\r\n            overflow: \"hidden\"\r\n        });\r\n\r\n        distance = vertical ? wrapper[ ref ]() + top : wrapper[ ref ]();\r\n\r\n        animation[ ref ] = show ? String(distance) : '0';\r\n        if ( !motion ) {\r\n            el\r\n                .css( vertical ? \"bottom\" : \"right\", 0 )\r\n                .css( vertical ? \"top\" : \"left\", \"\" )\r\n                .css({ position: \"absolute\" });\r\n            animation[ ref2 ] = show ? '0' : String(distance);\r\n        }\r\n\r\n        // // start at 0 if we are showing\r\n        if ( show ) {\r\n            wrapper.css( ref, 0 );\r\n            if ( ! motion ) {\r\n                wrapper.css( ref2, distance );\r\n            }\r\n        }\r\n\r\n        // // Animate\r\n        wrapper.animate( animation, {\r\n            duration: o.duration,\r\n            easing: o.easing,\r\n            queue: false,\r\n            complete: function() {\r\n                if ( mode === \"hide\" ) {\r\n                    el.hide();\r\n                }\r\n                $.jqplot.effects.restore( el, props );\r\n                $.jqplot.effects.removeWrapper( el );\r\n                done();\r\n            }\r\n        });\r\n\r\n    };\r\n\r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile-1.4.5.css",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n/* SVG icons */\n.ui-icon-action:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-alert:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8%20C6.447%2C8%2C6%2C7.553%2C6%2C7V5c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-audio:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-back:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-bars:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5%20C4.447%2C6%2C4%2C6.447%2C4%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1%20S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-camera:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2%20v6c0%2C1.104%2C0.896%2C2%2C2%2C2h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2%20C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-check:after,\n/* Used ui-checkbox-on twice to increase specificity. If active state has background-image for gradient this rule overrides. */\nhtml .ui-btn.ui-checkbox-on.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-clock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2%20c-0.158%2C0-0.311%2C0.023-0.457%2C0.058C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9%20c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-comment:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-delete:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-edit:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-eye:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-forward:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-gear:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-grid:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-heart:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C1.872c-2-3-7-2-7%2C2c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.479%2C3%2C3c0.583-0.521%2C3-3%2C3-3s4-4%2C4-7%20C14-0.128%2C9-1.128%2C7%2C1.872z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-home:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-info:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-location:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4%20s0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-lock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848%20C6.207%2C9.673%2C6%2C9.366%2C6%2C9c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-mail:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-minus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20style%3D%22fill%3A%23FFFFFF%3B%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-phone:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%22-0.01%200.008%2014%2014%22%20style%3D%22enable-background%3Anew%20-0.01%200.008%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M6.939%2C9.189C6.165%2C8.557%2C5.271%2C7.705%2C4.497%2C6.744C3.953%2C6.071%2C3.473%2C5.363%2C3.969%2C4.866l-3.482-3.48%20C-0.021%2C2.02-1.146%2C5.04%2C3.675%2C9.984c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.4C8.725%2C10.568%2C8.113%2C10.146%2C6.939%2C9.189z%20%20M13.82%2C11.519v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.211-0.546-0.205-0.754%2C0.002L9.455%2C9.831l3.403%2C3.407%20c0%2C0%2C0.962-0.96%2C0.961-0.961l0.002-0.001C14.043%2C12.056%2C14.021%2C11.721%2C13.82%2C11.519z%20M5.192%2C3.644V3.642%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.881c0%2C0-2.726-2.725-2.727-2.726C2.255-0.055%2C1.92-0.05%2C1.712%2C0.156L0.751%2C1.121l3.479%2C3.482%20C4.231%2C4.604%2C5.192%2C3.645%2C5.192%2C3.644z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-plus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-power:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455%20C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773%20C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773%20c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811%20C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1%20c-0.553%2C0-1%2C0.447-1%2C1v6C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11%20C4.791%2C11%2C3%2C9.209%2C3%2C7z%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4%20h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-search:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5%20s2.463%2C5.5%2C5.5%2C5.5c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-shop:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5%20S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5%20S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-star:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-tag:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-user:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-video:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n/* Alt icons */\n.ui-alt-icon.ui-icon-action:after,\n.ui-alt-icon .ui-icon-action:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-alert:after,\n.ui-alt-icon .ui-icon-alert:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8C6.447%2C8%2C6%2C7.553%2C6%2C7V5%20c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d:after,\n.ui-alt-icon .ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d-l:after,\n.ui-alt-icon .ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d-r:after,\n.ui-alt-icon .ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-l:after,\n.ui-alt-icon .ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-r:after,\n.ui-alt-icon .ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u:after,\n.ui-alt-icon .ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u-l:after,\n.ui-alt-icon .ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u-r:after,\n.ui-alt-icon .ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-audio:after,\n.ui-alt-icon .ui-icon-audio:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-back:after,\n.ui-alt-icon .ui-icon-back:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-bars:after,\n.ui-alt-icon .ui-icon-bars:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h12%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-bullets:after,\n.ui-alt-icon .ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5C4.447%2C6%2C4%2C6.447%2C4%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h8%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-calendar:after,\n.ui-alt-icon .ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-camera:after,\n.ui-alt-icon .ui-icon-camera:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2%20h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-d:after,\n.ui-alt-icon .ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-l:after,\n.ui-alt-icon .ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-r:after,\n.ui-alt-icon .ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-u:after,\n.ui-alt-icon .ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-check:after,\n.ui-alt-icon .ui-icon-check:after,\nhtml .ui-alt-icon.ui-btn.ui-checkbox-on:after,\nhtml .ui-alt-icon .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-clock:after,\n.ui-alt-icon .ui-icon-clock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-cloud:after,\n.ui-alt-icon .ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2c-0.158%2C0-0.311%2C0.023-0.457%2C0.058%20C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07%20C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-comment:after,\n.ui-alt-icon .ui-icon-comment:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-delete:after,\n.ui-alt-icon .ui-icon-delete:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-edit:after,\n.ui-alt-icon .ui-icon-edit:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-eye:after,\n.ui-alt-icon .ui-icon-eye:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-forbidden:after,\n.ui-alt-icon .ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-forward:after,\n.ui-alt-icon .ui-icon-forward:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-gear:after,\n.ui-alt-icon .ui-icon-gear:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-grid:after,\n.ui-alt-icon .ui-icon-grid:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-heart:after,\n.ui-alt-icon .ui-icon-heart:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C1.958c-2-3-7-2.128-7%2C1.872c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.48%2C3%2C3c0.583-0.52%2C3-3%2C3-3s4-4%2C4-7C14-0.169%2C9-1.042%2C7%2C1.958z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-home:after,\n.ui-alt-icon .ui-icon-home:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-info:after,\n.ui-alt-icon .ui-icon-info:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-location:after,\n.ui-alt-icon .ui-icon-location:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4s0.896-2%2C2-2%20c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-lock:after,\n.ui-alt-icon .ui-icon-lock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848C6.207%2C9.673%2C6%2C9.366%2C6%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-mail:after,\n.ui-alt-icon .ui-icon-mail:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-minus:after,\n.ui-alt-icon .ui-icon-minus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-navigation:after,\n.ui-alt-icon .ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-phone:after,\n.ui-alt-icon .ui-icon-phone:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M6.949%2C9.182C6.175%2C8.549%2C5.281%2C7.697%2C4.507%2C6.736C3.963%2C6.063%2C3.483%2C5.355%2C3.979%2C4.858l-3.482-3.48%20c-0.508%2C0.634-1.633%2C3.654%2C3.188%2C8.598c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.399C8.734%2C10.561%2C8.123%2C10.139%2C6.949%2C9.182z%20%20M13.83%2C11.512v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.212-0.546-0.205-0.754%2C0.002L9.465%2C9.823l3.402%2C3.407%20c0%2C0%2C0.963-0.961%2C0.961-0.961l0.002-0.002C14.053%2C12.049%2C14.031%2C11.713%2C13.83%2C11.512z%20M5.202%2C3.636V3.634%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.873c0%2C0-2.726-2.725-2.727-2.726c-0.21-0.21-0.545-0.205-0.753%2C0.001L0.761%2C1.113L4.24%2C4.595%20C4.241%2C4.596%2C5.202%2C3.637%2C5.202%2C3.636z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-plus:after,\n.ui-alt-icon .ui-icon-plus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-power:after,\n.ui-alt-icon .ui-icon-power:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773%20s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863%20c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365%20c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773%20C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1c-0.553%2C0-1%2C0.447-1%2C1v6%20C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-recycle:after,\n.ui-alt-icon .ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11C4.791%2C11%2C3%2C9.209%2C3%2C7z%20%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-refresh:after,\n.ui-alt-icon .ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-search:after,\n.ui-alt-icon .ui-icon-search:after,\n.ui-input-search:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5s2.463%2C5.5%2C5.5%2C5.5%20c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-shop:after,\n.ui-alt-icon .ui-icon-shop:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5%20S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5%20S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-star:after,\n.ui-alt-icon .ui-icon-star:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-tag:after,\n.ui-alt-icon .ui-icon-tag:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-user:after,\n.ui-alt-icon .ui-icon-user:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-video:after,\n.ui-alt-icon .ui-icon-video:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n/* PNG icons */\n.ui-nosvg .ui-icon-action:after {\n\tbackground-image: url(images/icons-png/action-white.png);\n}\n.ui-nosvg .ui-icon-alert:after {\n\tbackground-image: url(images/icons-png/alert-white.png);\n}\n.ui-nosvg .ui-icon-arrow-d-l:after {\n\tbackground-image: url(images/icons-png/arrow-d-l-white.png);\n}\n.ui-nosvg .ui-icon-arrow-d-r:after {\n\tbackground-image: url(images/icons-png/arrow-d-r-white.png);\n}\n.ui-nosvg .ui-icon-arrow-d:after {\n\tbackground-image: url(images/icons-png/arrow-d-white.png);\n}\n.ui-nosvg .ui-icon-arrow-l:after {\n\tbackground-image: url(images/icons-png/arrow-l-white.png);\n}\n.ui-nosvg .ui-icon-arrow-r:after {\n\tbackground-image: url(images/icons-png/arrow-r-white.png);\n}\n.ui-nosvg .ui-icon-arrow-u-l:after {\n\tbackground-image: url(images/icons-png/arrow-u-l-white.png);\n}\n.ui-nosvg .ui-icon-arrow-u-r:after {\n\tbackground-image: url(images/icons-png/arrow-u-r-white.png);\n}\n.ui-nosvg .ui-icon-arrow-u:after {\n\tbackground-image: url(images/icons-png/arrow-u-white.png);\n}\n.ui-nosvg .ui-icon-audio:after {\n\tbackground-image: url(images/icons-png/audio-white.png);\n}\n.ui-nosvg .ui-icon-back:after {\n\tbackground-image: url(images/icons-png/back-white.png);\n}\n.ui-nosvg .ui-icon-bars:after {\n\tbackground-image: url(images/icons-png/bars-white.png);\n}\n.ui-nosvg .ui-icon-bullets:after {\n\tbackground-image: url(images/icons-png/bullets-white.png);\n}\n.ui-nosvg .ui-icon-calendar:after {\n\tbackground-image: url(images/icons-png/calendar-white.png);\n}\n.ui-nosvg .ui-icon-camera:after {\n\tbackground-image: url(images/icons-png/camera-white.png);\n}\n.ui-nosvg .ui-icon-carat-d:after {\n\tbackground-image: url(images/icons-png/carat-d-white.png);\n}\n.ui-nosvg .ui-icon-carat-l:after {\n\tbackground-image: url(images/icons-png/carat-l-white.png);\n}\n.ui-nosvg .ui-icon-carat-r:after {\n\tbackground-image: url(images/icons-png/carat-r-white.png);\n}\n.ui-nosvg .ui-icon-carat-u:after {\n\tbackground-image: url(images/icons-png/carat-u-white.png);\n}\n.ui-nosvg .ui-icon-check:after,\nhtml.ui-nosvg .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(images/icons-png/check-white.png);\n}\n.ui-nosvg .ui-icon-clock:after {\n\tbackground-image: url(images/icons-png/clock-white.png);\n}\n.ui-nosvg .ui-icon-cloud:after {\n\tbackground-image: url(images/icons-png/cloud-white.png);\n}\n.ui-nosvg .ui-icon-comment:after {\n\tbackground-image: url(images/icons-png/comment-white.png);\n}\n.ui-nosvg .ui-icon-delete:after {\n\tbackground-image: url(images/icons-png/delete-white.png);\n}\n.ui-nosvg .ui-icon-edit:after {\n\tbackground-image: url(images/icons-png/edit-white.png);\n}\n.ui-nosvg .ui-icon-eye:after {\n\tbackground-image: url(images/icons-png/eye-white.png);\n}\n.ui-nosvg .ui-icon-forbidden:after {\n\tbackground-image: url(images/icons-png/forbidden-white.png);\n}\n.ui-nosvg .ui-icon-forward:after {\n\tbackground-image: url(images/icons-png/forward-white.png);\n}\n.ui-nosvg .ui-icon-gear:after {\n\tbackground-image: url(images/icons-png/gear-white.png);\n}\n.ui-nosvg .ui-icon-grid:after {\n\tbackground-image: url(images/icons-png/grid-white.png);\n}\n.ui-nosvg .ui-icon-heart:after {\n\tbackground-image: url(images/icons-png/heart-white.png);\n}\n.ui-nosvg .ui-icon-home:after {\n\tbackground-image: url(images/icons-png/home-white.png);\n}\n.ui-nosvg .ui-icon-info:after {\n\tbackground-image: url(images/icons-png/info-white.png);\n}\n.ui-nosvg .ui-icon-location:after {\n\tbackground-image: url(images/icons-png/location-white.png);\n}\n.ui-nosvg .ui-icon-lock:after {\n\tbackground-image: url(images/icons-png/lock-white.png);\n}\n.ui-nosvg .ui-icon-mail:after {\n\tbackground-image: url(images/icons-png/mail-white.png);\n}\n.ui-nosvg .ui-icon-minus:after {\n\tbackground-image: url(images/icons-png/minus-white.png);\n}\n.ui-nosvg .ui-icon-navigation:after {\n\tbackground-image: url(images/icons-png/navigation-white.png);\n}\n.ui-nosvg .ui-icon-phone:after {\n\tbackground-image: url(images/icons-png/phone-white.png);\n}\n.ui-nosvg .ui-icon-plus:after {\n\tbackground-image: url(images/icons-png/plus-white.png);\n}\n.ui-nosvg .ui-icon-power:after {\n\tbackground-image: url(images/icons-png/power-white.png);\n}\n.ui-nosvg .ui-icon-recycle:after {\n\tbackground-image: url(images/icons-png/recycle-white.png);\n}\n.ui-nosvg .ui-icon-refresh:after {\n\tbackground-image: url(images/icons-png/refresh-white.png);\n}\n.ui-nosvg .ui-icon-search:after {\n\tbackground-image: url(images/icons-png/search-white.png);\n}\n.ui-nosvg .ui-icon-shop:after {\n\tbackground-image: url(images/icons-png/shop-white.png);\n}\n.ui-nosvg .ui-icon-star:after {\n\tbackground-image: url(images/icons-png/star-white.png);\n}\n.ui-nosvg .ui-icon-tag:after {\n\tbackground-image: url(images/icons-png/tag-white.png);\n}\n.ui-nosvg .ui-icon-user:after {\n\tbackground-image: url(images/icons-png/user-white.png);\n}\n.ui-nosvg .ui-icon-video:after {\n\tbackground-image: url(images/icons-png/video-white.png);\n}\n/* Alt icons */\n.ui-nosvg .ui-alt-icon.ui-icon-action:after,\n.ui-nosvg .ui-alt-icon .ui-icon-action:after {\n\tbackground-image: url(images/icons-png/action-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-alert:after,\n.ui-nosvg .ui-alt-icon .ui-icon-alert:after {\n\tbackground-image: url(images/icons-png/alert-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-d:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-d:after {\n\tbackground-image: url(images/icons-png/arrow-d-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-l:after {\n\tbackground-image: url(images/icons-png/arrow-d-l-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-r:after {\n\tbackground-image: url(images/icons-png/arrow-d-r-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-l:after {\n\tbackground-image: url(images/icons-png/arrow-l-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-r:after {\n\tbackground-image: url(images/icons-png/arrow-r-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-u:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-u:after {\n\tbackground-image: url(images/icons-png/arrow-u-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-l:after {\n\tbackground-image: url(images/icons-png/arrow-u-l-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-r:after {\n\tbackground-image: url(images/icons-png/arrow-u-r-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-audio:after,\n.ui-nosvg .ui-alt-icon .ui-icon-audio:after {\n\tbackground-image: url(images/icons-png/audio-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-back:after,\n.ui-nosvg .ui-alt-icon .ui-icon-back:after {\n\tbackground-image: url(images/icons-png/back-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-bars:after,\n.ui-nosvg .ui-alt-icon .ui-icon-bars:after {\n\tbackground-image: url(images/icons-png/bars-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-bullets:after,\n.ui-nosvg .ui-alt-icon .ui-icon-bullets:after {\n\tbackground-image: url(images/icons-png/bullets-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-calendar:after,\n.ui-nosvg .ui-alt-icon .ui-icon-calendar:after {\n\tbackground-image: url(images/icons-png/calendar-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-camera:after,\n.ui-nosvg .ui-alt-icon .ui-icon-camera:after {\n\tbackground-image: url(images/icons-png/camera-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-d:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-d:after {\n\tbackground-image: url(images/icons-png/carat-d-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-l:after {\n\tbackground-image: url(images/icons-png/carat-l-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-r:after {\n\tbackground-image: url(images/icons-png/carat-r-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-u:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-u:after {\n\tbackground-image: url(images/icons-png/carat-u-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-check:after,\n.ui-nosvg .ui-alt-icon .ui-icon-check:after,\n.ui-nosvg .ui-alt-icon.ui-btn.ui-checkbox-on:after,\n.ui-nosvg .ui-alt-icon .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(images/icons-png/check-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-clock:after,\n.ui-nosvg .ui-alt-icon .ui-icon-clock:after {\n\tbackground-image: url(images/icons-png/clock-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-cloud:after,\n.ui-nosvg .ui-alt-icon .ui-icon-cloud:after {\n\tbackground-image: url(images/icons-png/cloud-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-comment:after,\n.ui-nosvg .ui-alt-icon .ui-icon-comment:after {\n\tbackground-image: url(images/icons-png/comment-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-delete:after,\n.ui-nosvg .ui-alt-icon .ui-icon-delete:after {\n\tbackground-image: url(images/icons-png/delete-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-edit:after,\n.ui-nosvg .ui-alt-icon .ui-icon-edit:after {\n\tbackground-image: url(images/icons-png/edit-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-eye:after,\n.ui-nosvg .ui-alt-icon .ui-icon-eye:after {\n\tbackground-image: url(images/icons-png/eye-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-forbidden:after,\n.ui-nosvg .ui-alt-icon .ui-icon-forbidden:after {\n\tbackground-image: url(images/icons-png/forbidden-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-forward:after,\n.ui-nosvg .ui-alt-icon .ui-icon-forward:after {\n\tbackground-image: url(images/icons-png/forward-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-gear:after,\n.ui-nosvg .ui-alt-icon .ui-icon-gear:after {\n\tbackground-image: url(images/icons-png/gear-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-grid:after,\n.ui-nosvg .ui-alt-icon .ui-icon-grid:after {\n\tbackground-image: url(images/icons-png/grid-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-heart:after,\n.ui-nosvg .ui-alt-icon .ui-icon-heart:after {\n\tbackground-image: url(images/icons-png/heart-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-home:after,\n.ui-nosvg .ui-alt-icon .ui-icon-home:after {\n\tbackground-image: url(images/icons-png/home-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-info:after,\n.ui-nosvg .ui-alt-icon .ui-icon-info:after {\n\tbackground-image: url(images/icons-png/info-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-location:after,\n.ui-nosvg .ui-alt-icon .ui-icon-location:after {\n\tbackground-image: url(images/icons-png/location-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-lock:after,\n.ui-nosvg .ui-alt-icon .ui-icon-lock:after {\n\tbackground-image: url(images/icons-png/lock-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-mail:after,\n.ui-nosvg .ui-alt-icon .ui-icon-mail:after {\n\tbackground-image: url(images/icons-png/mail-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-minus:after,\n.ui-nosvg .ui-alt-icon .ui-icon-minus:after {\n\tbackground-image: url(images/icons-png/minus-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-navigation:after,\n.ui-nosvg .ui-alt-icon .ui-icon-navigation:after {\n\tbackground-image: url(images/icons-png/navigation-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-phone:after,\n.ui-nosvg .ui-alt-icon .ui-icon-phone:after {\n\tbackground-image: url(images/icons-png/phone-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-plus:after,\n.ui-nosvg .ui-alt-icon .ui-icon-plus:after {\n\tbackground-image: url(images/icons-png/plus-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-power:after,\n.ui-nosvg .ui-alt-icon .ui-icon-power:after {\n\tbackground-image: url(images/icons-png/power-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-recycle:after,\n.ui-nosvg .ui-alt-icon .ui-icon-recycle:after {\n\tbackground-image: url(images/icons-png/recycle-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-refresh:after,\n.ui-nosvg .ui-alt-icon .ui-icon-refresh:after {\n\tbackground-image: url(images/icons-png/refresh-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-search:after,\n.ui-nosvg .ui-alt-icon .ui-icon-search:after,\n.ui-nosvg .ui-input-search:after {\n\tbackground-image: url(images/icons-png/search-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-shop:after,\n.ui-nosvg .ui-alt-icon .ui-icon-shop:after {\n\tbackground-image: url(images/icons-png/shop-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-star:after,\n.ui-nosvg .ui-alt-icon .ui-icon-star:after {\n\tbackground-image: url(images/icons-png/star-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-tag:after,\n.ui-nosvg .ui-alt-icon .ui-icon-tag:after {\n\tbackground-image: url(images/icons-png/tag-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-user:after,\n.ui-nosvg .ui-alt-icon .ui-icon-user:after {\n\tbackground-image: url(images/icons-png/user-black.png);\n}\n.ui-nosvg .ui-alt-icon.ui-icon-video:after,\n.ui-nosvg .ui-alt-icon .ui-icon-video:after {\n\tbackground-image: url(images/icons-png/video-black.png);\n}\n/* Globals */\n/* Font\n-----------------------------------------------------------------------------------------------------------*/\nhtml {\n\tfont-size: 100%;\n}\nbody,\ninput,\nselect,\ntextarea,\nbutton,\n.ui-btn {\n\tfont-size: 1em;\n\tline-height: 1.3;\n\tfont-family: sans-serif /*{global-font-family}*/;\n}\nlegend,\n.ui-input-text input,\n.ui-input-search input {\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n/* Form labels (overrides font-weight bold in bars, and mini font-size) */\n.ui-mobile label,\ndiv.ui-controlgroup-label {\n\tfont-weight: normal;\n\tfont-size: 16px;\n}\n/* Separators\n-----------------------------------------------------------------------------------------------------------*/\n/* Field contain separator (< 28em) */\n.ui-field-contain {\n\tborder-bottom-color: #828282;\n\tborder-bottom-color: rgba(0,0,0,.15);\n\tborder-bottom-width: 1px;\n\tborder-bottom-style: solid;\n}\n/* Table opt-in classes: strokes between each row, and alternating row stripes */\n/* Classes table-stroke and table-stripe are deprecated in 1.4. */\n.table-stroke thead th,\n.table-stripe thead th,\n.table-stripe tbody tr:last-child {\n\tborder-bottom: 1px solid #d6d6d6; /* non-RGBA fallback */\n\tborder-bottom: 1px solid rgba(0,0,0,.1);\n}\n.table-stroke tbody th,\n.table-stroke tbody td {\n\tborder-bottom: 1px solid #e6e6e6; /* non-RGBA fallback  */\n\tborder-bottom: 1px solid rgba(0,0,0,.05);\n}\n.table-stripe.table-stroke tbody tr:last-child th,\n.table-stripe.table-stroke tbody tr:last-child td {\n\tborder-bottom: 0;\n}\n.table-stripe tbody tr:nth-child(odd) td,\n.table-stripe tbody tr:nth-child(odd) th {\n\tbackground-color: #eeeeee; /* non-RGBA fallback  */\n\tbackground-color: rgba(0,0,0,.04);\n}\n/* Buttons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn,\nlabel.ui-btn {\n\tfont-weight: bold;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-btn {\n\ttext-decoration: none !important;\n}\n.ui-btn-active {\n\tcursor: pointer;\n}\n/* Corner rounding\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-btn-corner-all deprecated in 1.4 */\n.ui-corner-all {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-blocks}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-blocks}*/;\n}\n/* Buttons */\n.ui-btn-corner-all,\n.ui-btn.ui-corner-all,\n/* Slider track */\n.ui-slider-track.ui-corner-all,\n/* Flipswitch */\n.ui-flipswitch.ui-corner-all,\n/* Count bubble */\n.ui-li-count {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-buttons}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-buttons}*/;\n}\n/* Icon-only buttons */\n.ui-btn-icon-notext.ui-btn-corner-all,\n.ui-btn-icon-notext.ui-corner-all {\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Radius clip workaround for cleaning up corner trapping */\n.ui-btn-corner-all,\n.ui-corner-all {\n\t-webkit-background-clip: padding;\n\tbackground-clip: padding-box;\n}\n/* Popup arrow */\n.ui-popup.ui-corner-all > .ui-popup-arrow-guide {\n\tleft: .6em /*{global-radii-blocks}*/;\n\tright: .6em /*{global-radii-blocks}*/;\n\ttop: .6em /*{global-radii-blocks}*/;\n\tbottom: .6em /*{global-radii-blocks}*/;\n}\n/* Shadow\n-----------------------------------------------------------------------------------------------------------*/\n.ui-shadow {\n\t-webkit-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\tbox-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\t\t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n}\n.ui-shadow-inset {\n\t-webkit-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\tbox-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n}\n.ui-overlay-shadow {\n\t-webkit-box-shadow: 0 0 12px \t\trgba(0,0,0,.6);\n\t-moz-box-shadow: 0 0 12px \t\t\trgba(0,0,0,.6);\n\tbox-shadow: 0 0 12px \t\t\t\trgba(0,0,0,.6);\n}\n/* Icons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.3) /*{global-icon-disc}*/;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Alt icons */\n.ui-alt-icon.ui-btn:after,\n.ui-alt-icon .ui-btn:after,\nhtml .ui-alt-icon.ui-checkbox-off:after,\nhtml .ui-alt-icon.ui-radio-off:after,\nhtml .ui-alt-icon .ui-checkbox-off:after,\nhtml .ui-alt-icon .ui-radio-off:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.15) /*{global-icon-disc}*/;\n}\n/* No disc */\n.ui-nodisc-icon.ui-btn:after,\n.ui-nodisc-icon .ui-btn:after {\n\tbackground-color: transparent;\n}\n/* Icon shadow */\n.ui-shadow-icon.ui-btn:after,\n.ui-shadow-icon .ui-btn:after {\n\t-webkit-box-shadow: 0 1px 0 \t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\t-moz-box-shadow: 0 1px 0 \t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\tbox-shadow: 0 1px 0 \t\t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n}\n/* Checkbox and radio */\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after,\n.ui-btn.ui-radio-off:after,\n.ui-btn.ui-radio-on:after {\n\tdisplay: block;\n\twidth: 18px;\n\theight: 18px;\n\tmargin: -9px 2px 0 2px;\n}\n.ui-checkbox-off:after,\n.ui-btn.ui-radio-off:after {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n}\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after {\n\t-webkit-border-radius: .1875em;\n\tborder-radius: .1875em;\n}\n.ui-btn.ui-checkbox-off:after {\n\tbackground-color: #666;\n\tbackground-color: rgba(0,0,0,.3);\n}\n.ui-radio .ui-btn.ui-radio-on:after {\n\tbackground-image: none;\n\tbackground-color: #fff;\n\twidth: 8px;\n\theight: 8px;\n\tborder-width: 5px;\n\tborder-style: solid; \n}\n.ui-alt-icon.ui-btn.ui-radio-on:after,\n.ui-alt-icon .ui-btn.ui-radio-on:after {\n\tbackground-color: #000;\n}\n/* Loader */\n.ui-icon-loading {\n\tbackground: url(images/ajax-loader.gif);\n\tbackground-size: 2.875em 2.875em;\n}\n/* Swatches */\n/* A\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-a,\n.ui-page-theme-a .ui-bar-inherit,\nhtml .ui-bar-a .ui-bar-inherit,\nhtml .ui-body-a .ui-bar-inherit,\nhtml body .ui-group-theme-a .ui-bar-inherit {\n\tbackground-color: \t\t\t#e9e9e9 /*{a-bar-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bar-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bar-color}*/;\n\ttext-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 0 /*{a-bar-shadow-radius}*/ \t#eee /*{a-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-a,\n.ui-page-theme-a,\n.ui-page-theme-a .ui-panel-wrapper {\n\tbackground-color: \t\t\t#f9f9f9 /*{a-page-background-color}*/;\n\tborder-color:\t \t\t#bbb /*{a-page-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-page-color}*/;\n\ttext-shadow: 0 /*{a-page-shadow-x}*/ 1px /*{a-page-shadow-y}*/ 0 /*{a-page-shadow-radius}*/ \t#f3f3f3 /*{a-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-a,\n.ui-page-theme-a .ui-body-inherit,\nhtml .ui-bar-a .ui-body-inherit,\nhtml .ui-body-a .ui-body-inherit,\nhtml body .ui-group-theme-a .ui-body-inherit,\nhtml .ui-panel-page-container-a {\n\tbackground-color: \t\t\t#fff /*{a-body-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-body-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-body-color}*/;\n\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ \t#f3f3f3 /*{a-body-shadow-color}*/;\n}\n.ui-body-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-a a,\nhtml .ui-bar-a a,\nhtml .ui-body-a a,\nhtml body .ui-group-theme-a a {\n\tcolor: #3388cc /*{a-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-a a:visited,\nhtml .ui-bar-a a:visited,\nhtml .ui-body-a a:visited,\nhtml body .ui-group-theme-a a:visited {\n    color: #3388cc /*{a-link-visited}*/;\n}\n.ui-page-theme-a a:hover,\nhtml .ui-bar-a a:hover,\nhtml .ui-body-a a:hover,\nhtml body .ui-group-theme-a a:hover {\n\tcolor: #005599 /*{a-link-hover}*/;\n}\n.ui-page-theme-a a:active,\nhtml .ui-bar-a a:active,\nhtml .ui-body-a a:active,\nhtml body .ui-group-theme-a a:active {\n\tcolor: #005599 /*{a-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-a .ui-btn,\nhtml .ui-bar-a .ui-btn,\nhtml .ui-body-a .ui-btn,\nhtml body .ui-group-theme-a .ui-btn,\nhtml head + body .ui-btn.ui-btn-a,\n/* Button visited */\n.ui-page-theme-a .ui-btn:visited,\nhtml .ui-bar-a .ui-btn:visited,\nhtml .ui-body-a .ui-btn:visited,\nhtml body .ui-group-theme-a .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-a:visited {\n\tbackground-color: \t\t\t#f6f6f6 /*{a-bup-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bup-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bup-color}*/;\n\ttext-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #f3f3f3 /*{a-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-a .ui-btn:hover,\nhtml .ui-bar-a .ui-btn:hover,\nhtml .ui-body-a .ui-btn:hover,\nhtml body .ui-group-theme-a .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-a:hover {\n\tbackground-color: \t\t\t#ededed /*{a-bhover-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bhover-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bhover-color}*/;\n\ttext-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #f3f3f3 /*{a-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-a .ui-btn:active,\nhtml .ui-bar-a .ui-btn:active,\nhtml .ui-body-a .ui-btn:active,\nhtml body .ui-group-theme-a .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-a:active {\n\tbackground-color: \t\t\t#e8e8e8 /*{a-bdown-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bdown-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bdown-color}*/;\n\ttext-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #f3f3f3 /*{a-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-a .ui-btn.ui-btn-active,\nhtml .ui-bar-a .ui-btn.ui-btn-active,\nhtml .ui-body-a .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-a .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-a.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-a .ui-checkbox-on:after,\nhtml .ui-bar-a .ui-checkbox-on:after,\nhtml .ui-body-a .ui-checkbox-on:after,\nhtml body .ui-group-theme-a .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-a:after,\n/* Active flipswitch background */\n.ui-page-theme-a .ui-flipswitch-active,\nhtml .ui-bar-a .ui-flipswitch-active,\nhtml .ui-body-a .ui-flipswitch-active,\nhtml body .ui-group-theme-a .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-a .ui-slider-track .ui-btn-active,\nhtml .ui-bar-a .ui-slider-track .ui-btn-active,\nhtml .ui-body-a .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-a .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-a .ui-btn-active {\n\tbackground-color: \t\t#3388cc /*{a-active-background-color}*/;\n\tborder-color:\t \t\t#3388cc /*{a-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{a-active-color}*/;\n\ttext-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #005599 /*{a-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-a .ui-radio-on:after,\nhtml .ui-bar-a .ui-radio-on:after,\nhtml .ui-body-a .ui-radio-on:after,\nhtml body .ui-group-theme-a .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-a:after {\n\tborder-color:\t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-a .ui-btn:focus,\nhtml .ui-bar-a .ui-btn:focus,\nhtml .ui-body-a .ui-btn:focus,\nhtml body .ui-group-theme-a .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-a:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-a .ui-focus,\nhtml .ui-bar-a .ui-focus,\nhtml .ui-body-a .ui-focus,\nhtml body .ui-group-theme-a .ui-focus,\nhtml head + body .ui-btn-a.ui-focus,\nhtml head + body .ui-body-a.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#3388cc /*{a-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#3388cc /*{a-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* B\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-b,\n.ui-page-theme-b .ui-bar-inherit,\nhtml .ui-bar-b .ui-bar-inherit,\nhtml .ui-body-b .ui-bar-inherit,\nhtml body .ui-group-theme-b .ui-bar-inherit {\n\tbackground-color: \t\t\t#1d1d1d /*{b-bar-background-color}*/;\n\tborder-color:\t \t\t#1b1b1b /*{b-bar-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bar-color}*/;\n\ttext-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 0 /*{b-bar-shadow-radius}*/ \t#111 /*{b-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-b,\n.ui-page-theme-b,\n.ui-page-theme-b .ui-panel-wrapper {\n\tbackground-color: \t\t\t#252525 /*{b-page-background-color}*/;\n\tborder-color:\t \t\t#454545 /*{b-page-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-page-color}*/;\n\ttext-shadow: 0 /*{b-page-shadow-x}*/ 1px /*{b-page-shadow-y}*/ 0 /*{b-page-shadow-radius}*/ \t#111 /*{b-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-b,\n.ui-page-theme-b .ui-body-inherit,\nhtml .ui-bar-b .ui-body-inherit,\nhtml .ui-body-b .ui-body-inherit,\nhtml body .ui-group-theme-b .ui-body-inherit,\nhtml .ui-panel-page-container-b {\n\tbackground-color: \t\t\t#2a2a2a /*{b-body-background-color}*/;\n\tborder-color:\t \t\t#1d1d1d /*{b-body-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-body-color}*/;\n\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ \t#111 /*{b-body-shadow-color}*/;\n}\n.ui-body-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-b a,\nhtml .ui-bar-b a,\nhtml .ui-body-b a,\nhtml body .ui-group-theme-b a {\n\tcolor: #22aadd /*{b-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-b a:visited,\nhtml .ui-bar-b a:visited,\nhtml .ui-body-b a:visited,\nhtml body .ui-group-theme-b a:visited {\n    color: #22aadd /*{b-link-visited}*/;\n}\n.ui-page-theme-b a:hover,\nhtml .ui-bar-b a:hover,\nhtml .ui-body-b a:hover,\nhtml body .ui-group-theme-b a:hover {\n\tcolor: #0088bb /*{b-link-hover}*/;\n}\n.ui-page-theme-b a:active,\nhtml .ui-bar-b a:active,\nhtml .ui-body-b a:active,\nhtml body .ui-group-theme-b a:active {\n\tcolor: #0088bb /*{b-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-b .ui-btn,\nhtml .ui-bar-b .ui-btn,\nhtml .ui-body-b .ui-btn,\nhtml body .ui-group-theme-b .ui-btn,\nhtml head + body .ui-btn.ui-btn-b,\n/* Button visited */\n.ui-page-theme-b .ui-btn:visited,\nhtml .ui-bar-b .ui-btn:visited,\nhtml .ui-body-b .ui-btn:visited,\nhtml body .ui-group-theme-b .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-b:visited {\n\tbackground-color: \t\t\t#333 /*{b-bup-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bup-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n\ttext-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #111 /*{b-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-b .ui-btn:hover,\nhtml .ui-bar-b .ui-btn:hover,\nhtml .ui-body-b .ui-btn:hover,\nhtml body .ui-group-theme-b .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-b:hover {\n\tbackground-color: \t\t\t#373737 /*{b-bhover-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bhover-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n\ttext-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #111 /*{b-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-b .ui-btn:active,\nhtml .ui-bar-b .ui-btn:active,\nhtml .ui-body-b .ui-btn:active,\nhtml body .ui-group-theme-b .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-b:active {\n\tbackground-color: \t\t\t#404040 /*{b-bdown-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bdown-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n\ttext-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #111 /*{b-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-b .ui-btn.ui-btn-active,\nhtml .ui-bar-b .ui-btn.ui-btn-active,\nhtml .ui-body-b .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-b .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-b.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-b .ui-checkbox-on:after,\nhtml .ui-bar-b .ui-checkbox-on:after,\nhtml .ui-body-b .ui-checkbox-on:after,\nhtml body .ui-group-theme-b .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-b:after,\n/* Active flipswitch background */\n.ui-page-theme-b .ui-flipswitch-active,\nhtml .ui-bar-b .ui-flipswitch-active,\nhtml .ui-body-b .ui-flipswitch-active,\nhtml body .ui-group-theme-b .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-b .ui-slider-track .ui-btn-active,\nhtml .ui-bar-b .ui-slider-track .ui-btn-active,\nhtml .ui-body-b .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-b .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-b .ui-btn-active {\n\tbackground-color: \t\t#22aadd /*{b-active-background-color}*/;\n\tborder-color:\t \t\t#22aadd /*{b-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-active-color}*/;\n\ttext-shadow: 0 /*{b-active-shadow-x}*/ 1px /*{b-active-shadow-y}*/ 0 /*{b-active-shadow-radius}*/ #0088bb /*{b-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-b .ui-radio-on:after,\nhtml .ui-bar-b .ui-radio-on:after,\nhtml .ui-body-b .ui-radio-on:after,\nhtml body .ui-group-theme-b .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-b:after {\n\tborder-color:\t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-b .ui-btn:focus,\nhtml .ui-bar-b .ui-btn:focus,\nhtml .ui-body-b .ui-btn:focus,\nhtml body .ui-group-theme-b .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-b:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-b .ui-focus,\nhtml .ui-bar-b .ui-focus,\nhtml .ui-body-b .ui-focus,\nhtml body .ui-group-theme-b .ui-focus,\nhtml head + body .ui-btn-b.ui-focus,\nhtml head + body .ui-body-b.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#22aadd /*{b-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#22aadd /*{b-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Structure */\n/* Disabled\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-disabled deprecated in 1.4. :disabled not supported by IE8 so we use [disabled] */\n.ui-disabled,\n.ui-state-disabled,\nbutton[disabled],\n.ui-select .ui-btn.ui-state-disabled {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n\tcursor: default !important;\n\tpointer-events: none;\n}\n/* Focus state outline\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn:focus,\n.ui-btn.ui-focus {\n\toutline: 0;\n}\n/* Unset box-shadow in browsers that don't do it right */\n.ui-noboxshadow .ui-shadow,\n.ui-noboxshadow .ui-shadow-inset,\n.ui-noboxshadow .ui-overlay-shadow,\n.ui-noboxshadow .ui-shadow-icon.ui-btn:after,\n.ui-noboxshadow .ui-shadow-icon .ui-btn:after,\n.ui-noboxshadow .ui-focus,\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow  input:focus,\n.ui-noboxshadow .ui-panel {\n\t-webkit-box-shadow: none !important;\n\t-moz-box-shadow: none !important;\n\tbox-shadow: none !important;\n}\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow .ui-focus {\n\toutline-width: 1px;\n\toutline-style: auto;\n}\n/* Some unsets */\n.ui-mobile,\n.ui-mobile body {\n\theight: 99.9%;\n}\n.ui-mobile fieldset,\n.ui-page {\n\tpadding: 0;\n\tmargin: 0;\n}\n.ui-mobile a img,\n.ui-mobile fieldset {\n\tborder-width: 0;\n}\n/* Fixes for fieldset issues on IE10 and FF (see #6077) */\n.ui-mobile fieldset {\n\tmin-width: 0;\n}\n@-moz-document url-prefix() {\n\t.ui-mobile fieldset {\n\t\tdisplay: table-column;\n\t\tvertical-align: middle;\n\t}\n}\n/* Viewport */\n.ui-mobile-viewport {\n\tmargin: 0;\n\toverflow-x: visible;\n\t-webkit-text-size-adjust: 100%;\n\t-ms-text-size-adjust:none;\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n/* Issue #2066 */\nbody.ui-mobile-viewport,\ndiv.ui-mobile-viewport {\n\toverflow-x: hidden;\n}\n/* \"page\" containers - full-screen views, one should always be in view post-pageload */\n.ui-mobile [data-role=page],\n.ui-mobile [data-role=dialog],\n.ui-page {\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 100%;\n\tposition: absolute;\n\tdisplay: none;\n\tborder: 0;\n}\n/* On ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */\n.ui-page {\n\toutline: none;\n}\n.ui-mobile .ui-page-active {\n\tdisplay: block;\n\toverflow: visible;\n\toverflow-x: hidden;\n}\n@media screen and (orientation: portrait) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 420px;\n\t}\n}\n@media screen and (orientation: landscape) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 300px;\n\t}\n}\n/* Fouc */\n.ui-mobile-rendering > * {\n\tvisibility: hidden;\n}\n/* Non-js content hiding */\n.ui-nojs {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Loading screen */\n.ui-loading .ui-loader {\n\tdisplay: block;\n}\n.ui-loader {\n\tdisplay: none;\n\tz-index: 9999999;\n\tposition: fixed;\n\ttop: 50%;\n\tleft: 50%;\n\tborder:0;\n}\n.ui-loader-default {\n\tbackground: none;\n\tfilter: Alpha(Opacity=18);\n\topacity: .18;\n\twidth: 2.875em;\n\theight: 2.875em;\n\tmargin-left: -1.4375em;\n\tmargin-top: -1.4375em;\n}\n.ui-loader-verbose {\n\twidth: 12.5em;\n\tfilter: Alpha(Opacity=88);\n\topacity: .88;\n\tbox-shadow: 0 1px 1px -1px #fff;\n\theight: auto;\n\tmargin-left: -6.875em;\n\tmargin-top: -2.6875em;\n\tpadding: .625em;\n}\n.ui-loader-default h1 {\n\tfont-size: 0;\n\twidth: 0;\n\theight: 0;\n\toverflow: hidden;\n}\n.ui-loader-verbose h1 {\n\tfont-size: 1em;\n\tmargin: 0;\n\ttext-align: center;\n}\n.ui-loader .ui-icon-loading {\n\tbackground-color: #000;\n\tdisplay: block;\n\tmargin: 0;\n\twidth: 2.75em;\n\theight: 2.75em;\n\tpadding: .0625em;\n\t-webkit-border-radius: 2.25em;\n\tborder-radius: 2.25em;\n}\n.ui-loader-verbose .ui-icon-loading {\n\tmargin: 0 auto .625em;\n\tfilter: Alpha(Opacity=75);\n\topacity: .75;\n}\n.ui-loader-textonly {\n\tpadding: .9375em;\n\tmargin-left: -7.1875em;\n}\n.ui-loader-textonly .ui-icon-loading {\n\tdisplay: none;\n}\n.ui-loader-fakefix {\n\tposition: absolute;\n}\n/* Headers, content panels */\n.ui-bar,\n.ui-body {\n\tposition: relative;\n\tpadding: .4em 1em;\n\toverflow: hidden;\n\tdisplay: block;\n\tclear: both;\n}\n.ui-bar h1,\n.ui-bar h2,\n.ui-bar h3,\n.ui-bar h4,\n.ui-bar h5,\n.ui-bar h6 {\n\tmargin: 0;\n\tpadding: 0;\n\tfont-size: 1em;\n\tdisplay: inline-block;\n}\n.ui-header,\n.ui-footer {\n\tborder-width: 1px 0;\n\tborder-style: solid;\n\tposition: relative;\n}\n.ui-header:empty,\n.ui-footer:empty {\n\tmin-height: 2.6875em;\n}\n.ui-header .ui-title,\n.ui-footer .ui-title {\n\tfont-size: 1em;\n\tmin-height: 1.1em;\n\ttext-align: center;\n\tdisplay: block;\n\tmargin: 0 30%;\n\tpadding: .7em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\toutline: 0 !important;\n}\n.ui-footer .ui-title {\n\tmargin: 0 1em;\n}\n.ui-content {\n\tborder-width: 0;\n\toverflow: visible;\n\toverflow-x: hidden;\n\tpadding: 1em;\n}\n/* Corner styling for dialogs and popups */\n.ui-corner-all > .ui-header:first-child,\n.ui-corner-all > .ui-content:first-child,\n.ui-corner-all > .ui-footer:first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-corner-all > .ui-header:last-child,\n.ui-corner-all > .ui-content:last-child,\n.ui-corner-all > .ui-footer:last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n/* Buttons and icons */\n.ui-btn {\n\tfont-size: 16px;\n\tmargin: .5em 0;\n\tpadding: .7em 1em;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: center;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\tcursor: pointer;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n.ui-btn-icon-notext,\n.ui-header button.ui-btn.ui-btn-icon-notext,\n.ui-footer button.ui-btn.ui-btn-icon-notext {\n\tpadding: 0;\n\twidth: 1.75em;\n\theight: 1.75em;\n\ttext-indent: -9999px;\n\twhite-space: nowrap !important;\n}\n.ui-mini {\n\tfont-size: 12.5px;\n}\n.ui-mini .ui-btn {\n\tfont-size: inherit;\n}\n/* Make buttons in toolbars default to mini and inline. */\n.ui-header .ui-btn,\n.ui-footer .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-header .ui-controlgroup .ui-btn-icon-notext,\n.ui-footer .ui-controlgroup .ui-btn-icon-notext {\n    font-size: 12.5px;\n}\n/* To ensure same top and left/right position when ui-btn-left/right are added to something other than buttons. */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right {\n\tfont-size: 12.5px;\n}\n.ui-mini.ui-btn-icon-notext,\n.ui-mini .ui-btn-icon-notext,\n.ui-header .ui-btn-icon-notext,\n.ui-footer .ui-btn-icon-notext {\n\tfont-size: 16px;\t\n\tpadding: 0;\n}\n.ui-btn-inline {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin-right: .625em;\n}\n.ui-btn-icon-left {\n\tpadding-left: 2.5em;\n}\n.ui-btn-icon-right {\n\tpadding-right: 2.5em;\n}\n.ui-btn-icon-top {\n\tpadding-top: 2.5em;\n}\n.ui-btn-icon-bottom {\n\tpadding-bottom: 2.5em;\n}\n.ui-header .ui-btn-icon-top,\n.ui-footer .ui-btn-icon-top,\n.ui-header .ui-btn-icon-bottom,\n.ui-footer .ui-btn-icon-bottom {\n\tpadding-left: .3125em;\n\tpadding-right: .3125em;\n}\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tcontent: \"\";\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 22px;\n\theight: 22px;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after {\n\ttop: 50%;\n\tmargin-top: -11px;\n}\n.ui-btn-icon-left:after {\n\tleft: .5625em;\n}\n.ui-btn-icon-right:after {\n\tright: .5625em;\n}\n.ui-mini.ui-btn-icon-left:after,\n.ui-mini .ui-btn-icon-left:after,\n.ui-header .ui-btn-icon-left:after,\n.ui-footer .ui-btn-icon-left:after {\n\tleft: .37em;\n}\n.ui-mini.ui-btn-icon-right:after,\n.ui-mini .ui-btn-icon-right:after,\n.ui-header .ui-btn-icon-right:after,\n.ui-footer .ui-btn-icon-right:after {\n\tright: .37em;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after {\n\tleft: 50%;\n\tmargin-left: -11px;\n}\n.ui-btn-icon-top:after {\n\ttop: .5625em;\n}\n.ui-btn-icon-bottom:after {\n\ttop: auto;\n\tbottom: .5625em;\n}\n/* Buttons in header position classes */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right,\n.ui-btn-left > [class*=\"ui-\"],\n.ui-btn-right > [class*=\"ui-\"] {\n\tmargin: 0;\n}\n.ui-btn-left,\n.ui-btn-right {\n\tposition: absolute;\n\ttop: .24em;\n}\n.ui-btn-left {\n\tleft: .4em;\n}\n.ui-btn-right {\n\tright: .4em;\n}\n.ui-btn-icon-notext.ui-btn-left {\n\ttop: .3125em;\n\tleft: .3125em;\n}\n.ui-btn-icon-notext.ui-btn-right {\n\ttop: .3125em;\n\tright: .3125em;\n}\n/* Button elements */\nbutton.ui-btn,\n.ui-controlgroup-controls button.ui-btn-icon-notext {\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\twidth: 100%;\n}\nbutton.ui-btn-inline,\n.ui-header button.ui-btn,\n.ui-footer button.ui-btn {\n\twidth: auto;\n}\n/* Firefox adds a 1px border in a button element. We negate this to make sure they have the same height as other buttons in controlgroups. */\nbutton.ui-btn::-moz-focus-inner {\n\tborder: 0;\n}\nbutton.ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn {\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n\twidth: 1.75em;\n}\n/* Form labels */\n.ui-mobile label,\n.ui-controlgroup-label {\n\tdisplay: block;\n\tmargin: 0 0 .4em;\n}\n/* Accessible content hiding */\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-hide-label > label,\n.ui-hide-label .ui-controlgroup-label,\n.ui-hide-label .ui-rangeslider label,\n.ui-hidden-accessible {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Used for hiding elements by the filterable widget. You can also use this class to hide list items or buttons in controlgroups; this ensures correct corner styling. */\n.ui-screen-hidden {\n\tdisplay: none !important;\n}\n/* Transitions originally inspired by those from jQtouch, nice work, folks */\n.ui-mobile-viewport-transitioning,\n.ui-mobile-viewport-transitioning .ui-page {\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n.ui-page-pre-in {\n\topacity: 0;\n}\n.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.out {\n\t-webkit-animation-timing-function: ease-in;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-timing-function: ease-in;\n\t-moz-animation-duration: 225ms;\n\tanimation-timing-function: ease-in;\n\tanimation-duration: 225ms;\n}\n@-webkit-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-moz-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-webkit-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@-moz-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n.fade.out {\n\topacity: 0;\n\t-webkit-animation-duration: 125ms;\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-duration: 125ms;\n\t-moz-animation-name: fadeout;\n\tanimation-duration: 125ms;\n\tanimation-name: fadeout;\n}\n.fade.in {\n\topacity: 1;\n\t-webkit-animation-duration: 225ms;\n\t-webkit-animation-name: fadein;\n\t-moz-animation-duration: 225ms;\n\t-moz-animation-name: fadein;\n\tanimation-duration: 225ms;\n\tanimation-name: fadein;\n}\n.pop {\n\t-webkit-transform-origin: 50% 50%;\n\t-moz-transform-origin: 50% 50%;\n\ttransform-origin: 50% 50%;\n}\n.pop.in {\n\t-webkit-transform: scale(1);\n\t-webkit-animation-name: popin;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: scale(1);\n\t-moz-animation-name: popin;\n\t-moz-animation-duration: 350ms;\n\ttransform: scale(1);\n\tanimation-name: popin;\n\tanimation-duration: 350ms;\n    opacity: 1;\n}\n.pop.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n\topacity: 0;\n}\n.pop.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n\tanimation-name: fadein;\n}\n.pop.out.reverse {\n\t-webkit-transform: scale(.8);\n\t-webkit-animation-name: popout;\n\t-moz-transform: scale(.8);\n\t-moz-animation-name: popout;\n\ttransform: scale(.8);\n\tanimation-name: popout;\n}\n@-webkit-keyframes popin {\n    from {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n}\n@-moz-keyframes popin {\n    from {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n}\n@keyframes popin {\n    from {\n        transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        transform: scale(1);\n        opacity: 1;\n    }\n}\n@-webkit-keyframes popout {\n    from {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@-moz-keyframes popout {\n    from {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@keyframes popout {\n    from {\n        transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        transform: scale(.8);\n        opacity: 0;\n    }\n}\n/* keyframes for slidein from sides */\n@-webkit-keyframes slideinfromright {\n    from { -webkit-transform: translate3d(100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromright {\n    from { -moz-transform: translateX(100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromright {\n    from { transform: translateX(100%); }\n    to { transform: translateX(0); }\n}\n@-webkit-keyframes slideinfromleft {\n    from { -webkit-transform: translate3d(-100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromleft {\n    from { -moz-transform: translateX(-100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromleft {\n    from { transform: translateX(-100%); }\n    to { transform: translateX(0); }\n}\n/* keyframes for slideout to sides */\n@-webkit-keyframes slideouttoleft {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(-100%,0,0); }\n}\n@-moz-keyframes slideouttoleft {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(-100%); }\n}\n@keyframes slideouttoleft {\n    from { transform: translateX(0); }\n    to { transform: translateX(-100%); }\n}\n@-webkit-keyframes slideouttoright {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(100%,0,0); }\n}\n@-moz-keyframes slideouttoright {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(100%); }\n}\n@keyframes slideouttoright {\n    from { transform: translateX(0); }\n    to { transform: translateX(100%); }\n}\n.slide.out, .slide.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.slide.out {\n\t-webkit-transform: translate3d(-100%,0,0);\n\t-webkit-animation-name: slideouttoleft;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n}\n.slide.in {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromright;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromright;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromright;\n}\n.slide.out.reverse {\n\t-webkit-transform: translate3d(100%,0,0);\n\t-webkit-animation-name: slideouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n}\n.slide.in.reverse {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromleft;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromleft;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromleft;\n}\n.slidefade.out {\n\t-webkit-transform: translateX(-100%);\n\t-webkit-animation-name: slideouttoleft;\n\t-webkit-animation-duration: 225ms;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\t-moz-animation-duration: 225ms;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n\tanimation-duration: 225ms;\n}\n.slidefade.in {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n.slidefade.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: slideouttoright;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n\tanimation-duration: 200ms;\n}\n.slidefade.in.reverse {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n/* slide down */\n.slidedown.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slidedown.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfromtop;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfromtop;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfromtop;\n\tanimation-duration: 250ms;\n}\n.slidedown.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slidedown.out.reverse {\n\t-webkit-transform: translateY(-100%);\n\t-webkit-animation-name: slideouttotop;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(-100%);\n\t-moz-animation-name: slideouttotop;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(-100%);\n\tanimation-name: slideouttotop;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfromtop {\n    from { -webkit-transform: translateY(-100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfromtop {\n    from { -moz-transform: translateY(-100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfromtop {\n    from { transform: translateY(-100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttotop {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(-100%); }\n}\n@-moz-keyframes slideouttotop {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(-100%); }\n}\n@keyframes slideouttotop {\n    from { transform: translateY(0); }\n    to { transform: translateY(-100%); }\n}\n/* slide up */\n.slideup.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slideup.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfrombottom;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfrombottom;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfrombottom;\n\tanimation-duration: 250ms;\n}\n.slideup.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slideup.out.reverse {\n\t-webkit-transform: translateY(100%);\n\t-webkit-animation-name: slideouttobottom;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(100%);\n\t-moz-animation-name: slideouttobottom;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(100%);\n\tanimation-name: slideouttobottom;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfrombottom {\n    from { -webkit-transform: translateY(100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfrombottom {\n    from { -moz-transform: translateY(100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfrombottom {\n    from { transform: translateY(100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttobottom {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(100%); }\n}\n@-moz-keyframes slideouttobottom {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(100%); }\n}\n@keyframes slideouttobottom {\n    from { transform: translateY(0); }\n    to { transform: translateY(100%); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-flip {\n\t-webkit-perspective: 1000;\n\t-moz-perspective: 1000;\n\tperspective: 1000;\n\tposition: absolute;\n}\n.flip {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\tbackface-visibility: hidden;\n\ttransform: translateX(0);\n}\n.flip.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 175ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 175ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 175ms;\n}\n.flip.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 225ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 225ms;\n}\n.flip.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.flip.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-turn {\n\t-webkit-perspective: 200px;\n\t-moz-perspective: 200px;\n\t-ms-perspective: 200px;\n\tperspective: 200px;\n\tposition: absolute;\n}\n.turn {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-webkit-transform-origin: 0;\n\t\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\t-moz-transform-origin: 0;\n\t\n\tbackface-visibility :hidden;\n\ttransform: translateX(0);\n\ttransform-origin: 0;\n}\n.turn.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 125ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 125ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 125ms;\n}\n.turn.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 250ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 250ms;\n\t\n}\n.turn.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.turn.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* flow transition */\n.flow {\n\t-webkit-transform-origin: 50% 30%;\n\t-webkit-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\t-moz-transform-origin: 50% 30%;\t\n\t-moz-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\ttransform-origin: 50% 30%;\t\n\tbox-shadow: 0 0 20px rgba(0,0,0,.4);\n}\n.ui-dialog.flow {\n\t-webkit-transform-origin: none;\n\t-webkit-box-shadow: none;\n\t-moz-transform-origin: none;\t\n\t-moz-box-shadow: none;\n\ttransform-origin: none;\t\n\tbox-shadow: none;\n}\n.flow.out {\n\t-webkit-transform: translateX(-100%) scale(.7);\n\t-webkit-animation-name: flowouttoleft;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(-100%) scale(.7);\n\t-moz-animation-name: flowouttoleft;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(-100%) scale(.7);\n\tanimation-name: flowouttoleft;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.in {\n\t-webkit-transform: translateX(0) scale(1);\n\t-webkit-animation-name: flowinfromright;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(0) scale(1);\n\t-moz-animation-name: flowinfromright;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(0) scale(1);\n\tanimation-name: flowinfromright;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: flowouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: flowouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: flowouttoright;\n}\n.flow.in.reverse {\n\t-webkit-animation-name: flowinfromleft;\n\t-moz-animation-name: flowinfromleft;\n\tanimation-name: flowinfromleft;\n}\n@-webkit-keyframes flowouttoleft {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(-100%) scale(.7); }\n}\n@-moz-keyframes flowouttoleft {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(-100%) scale(.7); }\n}\n@keyframes flowouttoleft {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(-100%) scale(.7); }\n}\n@-webkit-keyframes flowouttoright {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform:  translateX(100%) scale(.7); }\n}\n@-moz-keyframes flowouttoright {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(100%) scale(.7); }\n}\n@keyframes flowouttoright {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(100%) scale(.7); }\n}\n@-webkit-keyframes flowinfromleft {\n    0% { -webkit-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromleft {\n    0% { -moz-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromleft {\n    0% { transform: translateX(-100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n@-webkit-keyframes flowinfromright {\n    0% { -webkit-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromright {\n    0% { -moz-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromright {\n    0% { transform: translateX(100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n.ui-field-contain,\n.ui-mobile fieldset.ui-field-contain {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n\tclear: both;\n\tpadding: .8em 0;\n}\n.ui-field-contain > label ~ [class*=\"ui-\"],\n.ui-field-contain .ui-controlgroup-controls {\n\tmargin: 0;\n}\n.ui-field-contain:last-child {\n\tborder-bottom-width: 0;\n}\n@media (min-width: 28em) {\n\t.ui-field-contain,\n\t.ui-mobile fieldset.ui-field-contain {\n\t\tpadding: 0;\n\t\tmargin: 1em 0;\n\t\tborder-bottom-width: 0;\n\t}\n\t.ui-field-contain:before,\n\t.ui-field-contain:after {\n\t\tcontent: \"\";\n\t\tdisplay: table;\n\t}\n\t.ui-field-contain:after {\n\t\tclear: both;\n\t}\n\t.ui-field-contain > label,\n\t.ui-field-contain .ui-controlgroup-label,\n\t.ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: left;\n\t\twidth: 20%;\n\t\tmargin: .5em 2% 0 0;\n\t}\n\t.ui-popup .ui-field-contain > label,\n\t.ui-popup .ui-field-contain .ui-controlgroup-label,\n\t.ui-popup .ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: none;\n\t\twidth: auto;\n\t\tmargin: 0 0 .4em;\n\t}\n\t.ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: left;\n\t\twidth: 78%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t}\n\t/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n\t.ui-hide-label > label ~ [class*=\"ui-\"],\n\t.ui-hide-label .ui-controlgroup-controls,\n\t.ui-popup .ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-popup .ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: none;\n\t\twidth: 100%;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline {\n\t\twidth: auto;\n\t\tmargin-right: .625em;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline.ui-btn-icon-notext {\n\t\twidth: 1.75em;\n\t}\n}\n/* content configurations. */\n.ui-grid-a,\n.ui-grid-b,\n.ui-grid-c,\n.ui-grid-d,\n.ui-grid-solo {\n\toverflow: hidden;\n}\n.ui-block-a,\n.ui-block-b,\n.ui-block-c,\n.ui-block-d,\n.ui-block-e {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfloat: left;\n\tmin-height: 1px;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n/* force new row */\n.ui-block-a {\n\tclear: left;\n}\nul.ui-grid-a,\nul.ui-grid-b,\nul.ui-grid-c,\nul.ui-grid-d,\nul.ui-grid-solo,\nli.ui-block-a,\nli.ui-block-b,\nli.ui-block-c,\nli.ui-block-d,\nli.ui-block-e {\n\tmargin-left: 0;\n\tmargin-right: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n/* No margin in grids for 100% width button elements until we can use max-width: fill-available; */\n[class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: 0;\n\tmargin-left: 0;\n}\n[class*=\"ui-block-\"] > .ui-btn,\n[class*=\"ui-block-\"] > .ui-select,\n[class*=\"ui-block-\"] > .ui-checkbox,\n[class*=\"ui-block-\"] > .ui-radio,\n[class*=\"ui-block-\"] > button.ui-btn-inline,\n[class*=\"ui-block-\"] > button.ui-btn-icon-notext,\n.ui-header [class*=\"ui-block-\"] > button.ui-btn,\n.ui-footer [class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: .3125em;\n\tmargin-left: .3125em;\n}\n.ui-grid-a > .ui-block-a,\n.ui-grid-a > .ui-block-b {\n\t/* width: 49.95%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 50%;\n}\n.ui-grid-b > .ui-block-a,\n.ui-grid-b > .ui-block-b,\n.ui-grid-b > .ui-block-c {\n\t/* width: 33.25%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 33.333%;\n}\n.ui-grid-c > .ui-block-a,\n.ui-grid-c > .ui-block-b,\n.ui-grid-c > .ui-block-c,\n.ui-grid-c > .ui-block-d {\n\t/* width: 24.925%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 25%;\n}\n.ui-grid-d > .ui-block-a,\n.ui-grid-d > .ui-block-b,\n.ui-grid-d > .ui-block-c,\n.ui-grid-d > .ui-block-d,\n.ui-grid-d > .ui-block-e {\n\t/* width: 19.925%; IE7 */\n\twidth: 20%;\n}\n.ui-grid-solo > .ui-block-a {\n\twidth: 100%;\n\tfloat: none; \n}\n/* preset breakpoint to switch to stacked grid styles below 35em (560px) */\n@media (max-width: 35em) {\n\t.ui-responsive > .ui-block-a,\n\t.ui-responsive > .ui-block-b,\n\t.ui-responsive > .ui-block-c,\n\t.ui-responsive > .ui-block-d,\n\t.ui-responsive > .ui-block-e {\n\t\twidth: 100%; \n\t\tfloat: none; \n\t}\n}\n/* fixed page header & footer configuration */\n.ui-header-fixed,\n.ui-footer-fixed {\n\tleft: 0;\n\tright: 0;\n\twidth: 100%;\n\tposition: fixed;\n\tz-index: 1000;\n}\n.ui-header-fixed {\n\ttop: -1px;\n\tpadding-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden {\n\ttop: 0;\n\tpadding-top: 0;\n}\n.ui-header-fixed .ui-btn-left,\n.ui-header-fixed .ui-btn-right {\n\tmargin-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden .ui-btn-left,\n.ui-header-fixed.ui-fixed-hidden .ui-btn-right {\n\tmargin-top: 0;\n}\n.ui-footer-fixed {\n\tbottom: -1px;\n\tpadding-bottom: 1px;\n}\n.ui-footer-fixed.ui-fixed-hidden {\n\tbottom: 0;\n\tpadding-bottom: 0;\n}\n.ui-header-fullscreen,\n.ui-footer-fullscreen {\n\tfilter: Alpha(Opacity=90);\n\topacity: .9;\n}\n/* updatePagePadding() will update the padding to actual height of header and footer. */\n.ui-page-header-fixed {\n\tpadding-top: 2.8125em;\n}\n.ui-page-footer-fixed {\n\tpadding-bottom: 2.8125em;\n}\n.ui-page-header-fullscreen > .ui-content,\n.ui-page-footer-fullscreen > .ui-content {\n\tpadding: 0;\n}\n.ui-fixed-hidden {\n\tposition: absolute;\n}\n/* Tap toggle: hide external fixed footer. See issue #6604 */\n.ui-footer-fixed.ui-fixed-hidden {\n  display: none;\n}\n.ui-page .ui-footer-fixed.ui-fixed-hidden {\n  display: block\n}\n.ui-page-header-fullscreen .ui-fixed-hidden,\n.ui-page-footer-fullscreen .ui-fixed-hidden {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-header-fixed .ui-btn,\n.ui-footer-fixed .ui-btn { \n\tz-index: 10;\n}\n/* workarounds for other widgets */\n.ui-android-2x-fixed .ui-li-has-thumb {\n\t-webkit-transform: translate3d(0,0,0);\n}\n.ui-navbar {\n\tmax-width: 100%;\n}\n.ui-navbar ul:before,\n.ui-navbar ul:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-navbar ul:after {\n\tclear: both;\n}\n.ui-navbar ul {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n\tdisplay: block;\n\tborder: 0;\n\tmax-width: 100%;\n\toverflow: visible;\n}\n.ui-navbar li .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: block;\n\tmargin: 0;\n\tborder-right-width: 0;\n}\n.ui-header .ui-navbar li button.ui-btn,\n.ui-footer .ui-navbar li button.ui-btn {\n\tmargin: 0;\n\twidth: 100%;\n}\n.ui-navbar .ui-btn:focus {\n\tz-index: 1;\n}\n/* fixes gaps caused by subpixel problem */\n.ui-navbar li:last-child .ui-btn {\n\tmargin-right: -4px;\n}\n.ui-navbar li:last-child .ui-btn:after {\n\tmargin-right: 4px;\n}\n.ui-content .ui-navbar li:last-child .ui-btn,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: 0;\n}\n.ui-content .ui-navbar li:last-child .ui-btn:after,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after {\n\tmargin-right: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after {\n\tmargin-right: 1px;\n}\n.ui-navbar .ui-grid-duo .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-header .ui-navbar .ui-btn,\n.ui-footer .ui-navbar .ui-btn {\n\tborder-top-width: 0;\n\tborder-bottom-width: 0;\n}\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-header .ui-title ~ .ui-navbar .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n/* Hide the native input element */\n.ui-input-btn input {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tbackground: #fff;\n\tbackground: rgba(255,255,255,0);\n\tfilter: Alpha(Opacity=0);\n\topacity: .1;\n\tfont-size: 1px;\n\ttext-indent: -9999px;\n\tz-index: 2;\n}\n/* Fixes IE/WP filter alpha opacity bugs */\n.ui-input-btn.ui-state-disabled input {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible {\n\tmargin: 0 -1em;\n}\n.ui-collapsible-inset,\n.ui-collapsible-set {\n\tmargin: .5em 0;\n}\n.ui-collapsible-heading {\n\tdisplay: block;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n}\n.ui-collapsible-heading .ui-btn {\n\ttext-align: left;\n\tmargin: 0;\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n}\n.ui-collapsible-heading .ui-btn-icon-top,\n.ui-collapsible-heading .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-collapsible-inset .ui-collapsible-heading .ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-collapsible-collapsed + .ui-collapsible:not(.ui-collapsible-inset) > .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-collapsible-heading-status {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible-content {\n\tdisplay: block;\n\tmargin: 0;\t\n\tpadding: .5em 1em;\n}\n.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n\tborder-top-width: 0;\n\tborder-bottom-width: 1px;\n\tborder-style: solid;\n}\n.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 1px;\n\tborder-right-width: 1px;\n}\n.ui-collapsible-inset .ui-collapsible-content {\n\tmargin: 0;\n}\n.ui-collapsible-content-collapsed {\n\tdisplay: none;\n}\n.ui-collapsible-set > .ui-collapsible.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-collapsible-heading,\n.ui-collapsible-heading > .ui-btn {\n\t-webkit-border-radius: inherit;\t\n\tborder-radius: inherit;\t\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\t\n\tborder-top-left-radius: inherit;\t\t\n}\n.ui-collapsible-content,\n.ui-collapsible-set .ui-collapsible.ui-last-child {\n\t-webkit-border-bottom-right-radius: inherit;\t\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\t\n\tborder-bottom-left-radius: inherit;\t\t\n}\n.ui-collapsible-themed-content:not(.ui-collapsible-collapsed) > .ui-collapsible-heading {\n\t-webkit-border-bottom-right-radius: 0;\t\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\t\n\tborder-bottom-left-radius: 0;\t\t\n}\n.ui-collapsible-set .ui-collapsible {\n\tmargin: -1px -1em 0;\n}\n.ui-collapsible-set .ui-collapsible-inset {\n\tmargin: -1px 0 0;\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\tmargin-top: 0;\n}\n.ui-controlgroup,\nfieldset.ui-controlgroup {\n\tpadding: 0;\n\tmargin: .5em 0;\n}\n.ui-field-contain .ui-controlgroup,\n.ui-field-contain fieldset.ui-controlgroup {\n\tmargin: 0;\n}\n.ui-mini .ui-controlgroup-label {\n\tfont-size: 16px;\n}\n.ui-controlgroup.ui-mini .ui-btn-icon-notext,\n.ui-controlgroup .ui-mini.ui-btn-icon-notext {\n\tfont-size: inherit;\n}\n.ui-controlgroup-controls .ui-btn,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-select {\n\tmargin: 0;\n}\n.ui-controlgroup-controls .ui-btn:focus,\n.ui-controlgroup-controls .ui-btn.ui-focus {\n\tz-index: 1;\n}\n.ui-controlgroup-controls li {\n\tlist-style: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:before,\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tclear: both;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls li > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select {\n\tfloat: left;\n\tclear: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,\n.ui-controlgroup-controls .ui-btn-icon-notext {\n\twidth: auto;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext {\n\twidth: 1.5em;\n}\n .ui-controlgroup-controls .ui-btn-icon-notext {\n\theight: auto;\n\tpadding: .7em 1em;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-bottom-width: 1px;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn {\n\tborder-right-width: 0;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-right-width: 1px;\n}\n.ui-controlgroup-controls .ui-btn-corner-all,\n.ui-controlgroup-controls .ui-btn.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-controlgroup-controls,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-select,\n.ui-controlgroup-controls li {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-last-child {\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-controls a.ui-shadow:not(:focus),\n.ui-controlgroup-controls button.ui-shadow:not(:focus),\n.ui-controlgroup-controls div.ui-shadow:not(.ui-focus) {\n\t-moz-box-shadow: none;\n\t-webkit-box-shadow: none;\n\tbox-shadow: none;\n}\n/* Fixes legend not wrapping on IE10 */\n.ui-controlgroup-label legend {\n\tmax-width: 100%;\n}\n.ui-controlgroup-controls > label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-dialog {\n\t background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */\n}\n.ui-dialog-contain {\n\twidth: 92.5%;\n\tmax-width: 500px;\n\tmargin: 10% auto 1em auto;\n\tpadding: 0;\n\tposition: relative;\n\ttop: -1em;\n}\n.ui-dialog-contain > .ui-header, \n.ui-dialog-contain > .ui-content, \n.ui-dialog-contain > .ui-footer { \n\tdisplay: block;\n\tposition: relative; \n\twidth: auto;\n\tmargin: 0;\n}\n.ui-dialog-contain > .ui-header {\n\toverflow: hidden;\n\tz-index: 10; \n\tpadding: 0;\n\tborder-top-width: 0;\n}\n.ui-dialog-contain > .ui-footer {\n\tz-index: 10; \n\tpadding: 0 1em; \n\tborder-bottom-width: 0;\n}\n.ui-popup-open .ui-header-fixed,\n.ui-popup-open .ui-footer-fixed {\n\tposition: absolute !important; /* See issues #4816, #4844 and #4874 and popup.js */\n}\n.ui-popup-screen {\n\tbackground-image: url(\"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\"); /* Necessary to set some form of background to ensure element is clickable in IE6/7. While legacy IE won't understand the data-URI'd image, it ensures no additional requests occur in all other browsers with little overhead. */\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 1px;\n\tposition: absolute;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 1099;\n}\n.ui-popup-screen.in {\n\topacity: 0.5;\n\tfilter: Alpha(Opacity=50);\n}\n.ui-popup-screen.out {\n\topacity: 0;\n\tfilter: Alpha(Opacity=0);\n}\n.ui-popup-container {\n\tz-index: 1100;\n\tdisplay: inline-block;\n\tposition: absolute;\n\tpadding: 0;\n\toutline: 0;\n}\n.ui-popup {\n\tposition: relative;\n}\n.ui-popup.ui-body-inherit {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-hidden {\n\tleft: 0;\n\ttop: 0;\n\tposition: absolute !important;\n\tvisibility: hidden;\n}\n.ui-popup-truncate {\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-popup.ui-content,\n.ui-popup .ui-content {\n\toverflow: visible;\n}\n.ui-popup > .ui-header {\n\tborder-top-width: 0;\n}\n.ui-popup > .ui-footer {\n\tborder-bottom-width: 0;\n}\n.ui-popup > p,\n.ui-popup > h1,\n.ui-popup > h2,\n.ui-popup > h3,\n.ui-popup > h4,\n.ui-popup > h5,\n.ui-popup > h6 {\n\tmargin: .5em .4375em;\n}\n.ui-popup > span {\n\tdisplay: block;\n\tmargin: .5em .4375em;\n}\n.ui-popup-container .ui-content > p,\n.ui-popup-container .ui-content > h1,\n.ui-popup-container .ui-content > h2,\n.ui-popup-container .ui-content > h3,\n.ui-popup-container .ui-content > h4,\n.ui-popup-container .ui-content > h5,\n.ui-popup-container .ui-content > h6 {\n\tmargin: .5em 0;\n}\n.ui-popup-container .ui-content > span {\n\tmargin: 0;\n}\n.ui-popup-container .ui-content > p:first-child,\n.ui-popup-container .ui-content > h1:first-child,\n.ui-popup-container .ui-content > h2:first-child,\n.ui-popup-container .ui-content > h3:first-child,\n.ui-popup-container .ui-content > h4:first-child,\n.ui-popup-container .ui-content > h5:first-child,\n.ui-popup-container .ui-content > h6:first-child {\n\tmargin-top: 0;\n}\n.ui-popup-container .ui-content > p:last-child,\n.ui-popup-container .ui-content > h1:last-child,\n.ui-popup-container .ui-content > h2:last-child,\n.ui-popup-container .ui-content > h3:last-child,\n.ui-popup-container .ui-content > h4:last-child,\n.ui-popup-container .ui-content > h5:last-child,\n.ui-popup-container .ui-content > h6:last-child {\n\tmargin-bottom: 0;\n}\n.ui-popup > img {\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tvertical-align: middle;\n}\n.ui-popup:not(.ui-content) > img:only-child,\n.ui-popup:not(.ui-content) > .ui-btn-left:first-child + img:last-child,\n.ui-popup:not(.ui-content) > .ui-btn-right:first-child + img:last-child {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-popup iframe {\n\tvertical-align: middle;\n}\n.ui-popup > .ui-btn-left,\n.ui-popup > .ui-btn-right {\n\tposition: absolute; \n\ttop: -11px;\n\tmargin: 0;\n\tz-index: 1101;\n}\n.ui-popup > .ui-btn-left {\n\tleft: -11px;\n}\n.ui-popup > .ui-btn-right {\n\tright: -11px;\n}\n/* Dimensions related to the popup arrow\n-----------------------------------------------------------------------------------------------------------*/\n/* desired triangle height: 10px */\n/**\n * guide for the arrow - its width, height, and offset are theme-dependent and\n * should be expessed as left, right, top, bottom, so that the element bearing\n * such a class becomes stretched inside its parent position: relative element.\n * The left/top/right/bottom specified below should reflect the corresponding\n * border radii and so it leaves room for the shadow:\n *     ..--------------------..\n *   .\"        ^ top           \".\n *  /          v                 \\\n * |     +------------------+     |\n * |     |                  |     |\n * | left|                  |right|\n * |<--->|                  |<--->|\n * |     +------------------+     |\n *  \\          ^                 /\n *   `.        v bottom        .'\n *     \"\"--------------------\"\"\n * The idea is that the top/left of the arrow container box does not move to a\n * coordinate smaller than the top/left of the guide and the right/bottom of\n * the arrow container box does not move to a coordinate larger than the\n * bottom/right of the guide. This will help us avoid the following situation:\n *        ..--------------------..\n *      .\"        ^ top           \".\n *   /|/          v                 \\\n *  / |     +------------------+     |\n *  \\ |     |                  |     |\n *   \\| left|                  |right|\n *    |<--->|                  |<--->|\n *    |     +------------------+     |\n *     \\          ^                 /\n *      `.        v bottom        .'\n *        \"\"--------------------\"\"\n * The arrow should not receive a top/left coordinate such that it is too close\n * to one of the corners, because then at first the shadow of the arrow and,\n * given a coordinate even closer to the corner, even the body of the arrow will\n * \"stick out\" of the corner of the popup. The guide provides a hint to the\n * arrow positioning code as to which range of values is acceptable for the\n * arrow container's top/left coordinate.\n **/\n.ui-popup-arrow-container {\n\twidth: 20px;\n\theight: 20px;\n}\n/* aside from the \"infinities\" (-1000,2000), triangle height is used */\n.ui-popup-arrow-container.ui-popup-arrow-l {\n\tleft: -10px;\n\tclip: rect(-1000px,10px,2000px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-t {\n\ttop: -10px;\n\tclip: rect(-1000px,2000px,10px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-r {\n\tright: -10px;\n\tclip: rect(-1000px,2000px,2000px,10px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-b {\n\tbottom: -10px;\n\tclip: rect(10px,2000px,1000px,-1000px);\n}\n/**\n * For each side, the arrow is twice the desired size and its corner is aligned\n * with the edge of the container:\n *                                           \n *           /\\         /\\                +----+       /\\\n *          /  \\       /  \\               | /\\ |top   /  \\\n *      +----+  \\     /  +----+       +-->|/  \\|     /    \\\n *  left| /  |   \\   /   |  \\ |right  |   |    |    /      \\\n *      |/   |    \\ /    |   \\|       |  /|    |\\  /        \\\n *      |\\   |    / \\    |   /|       | / +----+ \\ \\ +----+ /\n *      | \\  |   /   \\   |  / |       | \\        /  \\|    |/\n *      +----+  /     \\  +----+       |  \\      /    |    |\n *       ^  \\  /       \\  /  ^        |   \\    /  +->|\\  /|\n *       |   \\/         \\/   |        |    \\  /   |  | \\/ |bottom\n *       |                   |        |     \\/    |  +----+\n *       +-------------------+--------+-----------+\n *                           |\n *                    arrow container\n *                     (clips arrow)\n **/\n.ui-popup-arrow-container .ui-popup-arrow {\n\t/* (4*desired triangle height)/sqrt(2) - does not account for border - centred within the outer rectangle */\n\twidth: 28.284271247px;\n\theight: 28.284271247px;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: 5.857864376px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: -14.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow {\n\tleft: 5.857864376px;\n\ttop: -4.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow {\n\tleft: -14.142135623px;\n\ttop: -4.142135623px;\n}\n/* Fix rotation center for oldIE - see http://www.useragentman.com/IETransformsTranslator/ */\n.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -7.0710678118654755px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -4.142135623730951px;\n}\n \n.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow {\n    margin-left: -7.0710678118654755px;\n    margin-top: -5.857864376269049px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow {\n    margin-left: -4.142135623730951px;\n    margin-top: -5.857864376269049px;\n}\n/* structure */\n.ui-popup > .ui-popup-arrow-guide {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tvisibility: hidden;\n}\n.ui-popup-arrow-container {\n\tposition: absolute;\n}\n.ui-popup-arrow {\n\t-webkit-transform: rotate(45deg);\n\t-moz-transform: rotate(45deg);\n\t-ms-transform: rotate(45deg);\n\ttransform: rotate(45deg);\n\tposition: absolute;\n\toverflow: hidden;\n\tbox-sizing: border-box;\n}\n.ui-popup-arrow-container.ie .ui-popup-arrow {\n\t-ms-filter: \"progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod='auto expand')\";\n\tfilter: progid:DXImageTransform.Microsoft.Matrix(\n\t      \tM11=0.7071067811865474,\n        \tM12=-0.7071067811865477,\n        \tM21=0.7071067811865477,\n        \tM22=0.7071067811865474,\n        \tSizingMethod='auto expand');\n}\n.ui-checkbox,\n.ui-radio {\n\tmargin: .5em 0;\n\tposition: relative;\n}\n.ui-checkbox .ui-btn,\n.ui-radio .ui-btn {\n\tmargin: 0;\n\ttext-align: left;\n\twhite-space: normal; /* Nowrap + ellipsis doesn't work on label. Issue #1419. */\n\tz-index: 2;\n}\n.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,\n.ui-controlgroup .ui-radio .ui-btn.ui-focus {\n\tz-index: 3;\n}\n.ui-checkbox .ui-btn-icon-top,\n.ui-radio .ui-btn-icon-top,\n.ui-checkbox .ui-btn-icon-bottom,\n.ui-radio .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,\n.ui-controlgroup-horizontal .ui-radio .ui-btn:after {\n\tcontent: none;\n\tdisplay: none;\n}\n/* Native input positioning */\n.ui-checkbox input,\n.ui-radio input {\n\tposition: absolute;\n\tleft: .466em;\n\ttop: 50%;\n\twidth: 22px;\n\theight: 22px;\n\tmargin: -11px 0 0 0;\n\toutline: 0 !important;\n\tz-index: 1;\n}\n.ui-controlgroup-horizontal .ui-checkbox input,\n.ui-controlgroup-horizontal .ui-radio input {\n\tleft: 50%;\n\tmargin-left: -9px;\n}\n.ui-checkbox input:disabled,\n.ui-radio input:disabled {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select {\n\tmargin-top: .5em;\n\tmargin-bottom: .5em; /* no shorthand for margin because it would override margin-right for inline selects */\n\tposition: relative;\n}\n.ui-select > select {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select .ui-btn {\n\tmargin: 0;\n\topacity: 1; /* Fixes #2588: When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select (including \"inherit\") without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */\n}\n.ui-select .ui-btn select {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 1.5em;\n\tmin-height: 100%;\n\theight: 3em;\n\tmax-height: 100%;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 2;\n}\n@-moz-document url-prefix() {\n\t.ui-select .ui-btn select {\n\t\topacity: 0.0001;\n\t}\n}\n/* Display none because of issues with IE/WP's filter alpha opacity */\n.ui-select .ui-state-disabled select {\n\tdisplay: none;\n}\n/* Because we add all classes of the select and option elements to the span... */ \n.ui-select span.ui-state-disabled {\n\tfilter: Alpha(Opacity=100);\n\topacity: 1;\n}\n.ui-select .ui-btn.ui-select-nativeonly {\n\tborder-radius: 0;\n\tborder: 0;\n}\n.ui-select .ui-btn.ui-select-nativeonly select {\n\topacity: 1;\n\ttext-indent: 0;\n\tdisplay: block;\n}\n/* ui-li-count is styled in the listview CSS. We set padding and offset here because select supports icon position while listview doesn't. */\n.ui-select .ui-li-has-count.ui-btn {\n\tpadding-right: 2.8125em;\n}\n.ui-select .ui-li-has-count.ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-select .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n/* We set the rules for the span as well to fix an issue on Chrome with text-overflow ellipsis for the button in combination with text-align center. */\n.ui-select .ui-btn > span:not(.ui-li-count) {\n\tdisplay: block;\n\ttext-overflow: ellipsis;\n\toverflow: hidden !important;\n\twhite-space: nowrap;\n}\n.ui-selectmenu.ui-popup {\n\tmin-width: 11em;\n}\n.ui-selectmenu .ui-dialog-contain {\n\toverflow: hidden;\n}\n.ui-selectmenu .ui-header {\n\tmargin: 0;\n\tpadding: 0;\n\tborder-width: 0;\n}\n.ui-selectmenu.ui-dialog .ui-header {\n\tz-index: 1;\n\tposition: relative;\n}\n.ui-selectmenu.ui-popup .ui-header {\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n}\n/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button.  this shim's content in there */\n.ui-selectmenu.ui-popup .ui-header h1:after {\n\tcontent: '.';\n\tvisibility: hidden;\n}\n.ui-selectmenu .ui-header .ui-title {\n\tmargin: 0 2.875em;\n}\n.ui-selectmenu.ui-dialog .ui-content {\n\toverflow: visible;\n\tz-index: 1;\n}\n.ui-selectmenu .ui-selectmenu-list {\n\tmargin: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-header:not(.ui-screen-hidden) + .ui-selectmenu-list {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-top-left-radius: 0;\n\tborder-top-left-radius: 0;\n}\n.ui-header.ui-screen-hidden + .ui-selectmenu-list li.ui-first-child .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-selectmenu .ui-btn.ui-li-divider {\n\tcursor: default;\n}\n.ui-selectmenu .ui-selectmenu-placeholder {\n\tdisplay: none;\n}\n.ui-listview,\n.ui-listview > li {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n.ui-content .ui-listview,\n.ui-panel-inner > .ui-listview {\n\tmargin: -1em;\n}\n.ui-content .ui-listview-inset,\n.ui-panel-inner > .ui-listview-inset {\n\tmargin: 1em 0;\n}\n.ui-collapsible-content > .ui-listview {\n\tmargin: -.5em -1em;\n}\n.ui-collapsible-content > .ui-listview-inset {\n\tmargin: .5em 0;\n}\n.ui-listview > li {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tmargin: 0;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: left;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li > .ui-btn:focus {\n\tz-index: 1;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tborder-width: 1px 0 0 0;\n\tborder-style: solid;\n}\n.ui-listview-inset > .ui-li-static,\n.ui-listview-inset > .ui-li-divider,\n.ui-listview-inset > li > a.ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-listview > .ui-li-static.ui-last-child,\n.ui-listview > .ui-li-divider.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 1px;\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child,\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-listview > li.ui-first-child,\n.ui-listview > li.ui-first-child > a.ui-btn {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n}\n.ui-listview > li.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-listview > li.ui-li-has-alt > a.ui-btn {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n.ui-listview > li.ui-first-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-top-left-radius: 0;\t\n\tborder-top-left-radius: 0;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-listview > li.ui-last-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-listview > li.ui-first-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\t\n}\n.ui-listview > li.ui-last-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\t\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-listview > .ui-li-static {\n\tpadding: .7em 1em;\n}\n.ui-listview > .ui-li-divider {\n\tpadding: .5em 1.143em;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tcursor: default;\n\toutline: 0; /* Dividers in custom selectmenus have tabindex */\n}\n.ui-listview > .ui-li-has-count > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-count,\n.ui-listview > .ui-li-divider.ui-li-has-count {\n\tpadding-right: 2.8125em;\n}\n.ui-listview > .ui-li-has-count > .ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-listview > .ui-li-has-thumb > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-thumb {\n\tmin-height: 3.625em;\n\tpadding-left: 6.25em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-icon {\n\tmin-height: 1.25em;\n\tpadding-left: 2.5em;\n}\n/* Used by both listview and custom multiple select button */\n.ui-li-count {\n\tposition: absolute;\n\tfont-size: 12.5px;\n\tfont-weight: bold;\n\ttext-align: center;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tpadding: 0 .48em;\n\tline-height: 1.6em;\n\tmin-height: 1.6em;\n\tmin-width: .64em;\n\tright: .8em;\n\ttop: 50%;\n\tmargin-top: -.88em;\n}\n.ui-listview .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n.ui-listview .ui-li-has-thumb > img:first-child,\n.ui-listview .ui-li-has-thumb > .ui-btn > img:first-child,\n.ui-listview .ui-li-has-thumb .ui-li-thumb {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\tmax-height: 5em;\n\tmax-width: 5em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > img:first-child,\n.ui-listview > .ui-li-has-icon > .ui-btn > img:first-child {\n\tposition: absolute;\n\tleft: .625em;\n\ttop: .9em;\n\tmax-height: 1em;\n\tmax-width: 1em;\n}\n.ui-listview > li h1,\n.ui-listview > li h2,\n.ui-listview > li h3,\n.ui-listview > li h4,\n.ui-listview > li h5,\n.ui-listview > li h6 {\n\tfont-size: 1em;\n\tfont-weight: bold;\n\tdisplay: block;\n\tmargin: .45em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li p {\n\tfont-size: .75em;\n\tfont-weight: normal;\n\tdisplay: block;\n\tmargin: .6em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview .ui-li-aside {\n\tposition: absolute;\n\ttop: 1em;\n\tright: 3.333em;\n\tmargin: 0;\n\ttext-align: right;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn {\n\tmargin-right: 2.5em;\n\tborder-right-width: 0;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tposition: absolute;\n\twidth: 2.5em;\n\theight: 100%;\n\tmin-height: auto;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-left-width: 1px;\n\ttop: 0;\n\tright: 0;\n\tmargin: 0;\n\tpadding: 0;\n\tz-index: 2;\n}\n.ui-listview-inset > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tborder-right-width: 1px;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn:focus {\n\tz-index: 3;\n}\nol.ui-listview,\nol.ui-listview > .ui-li-divider {\n\tcounter-reset: listnumbering;\n}\nol.ui-listview > li > .ui-btn,\nol.ui-listview > li.ui-li-static {\n\tvertical-align: middle;\n}\nol.ui-listview > li > .ui-btn:first-child:before,\nol.ui-listview > li.ui-li-static:before,\nol.ui-listview > li.ui-field-contain > label:before,\nol.ui-listview > li.ui-field-contain > .ui-controlgroup-label:before {\n\tdisplay: inline-block;\n\tfont-size: .9em;\n\tfont-weight: normal;\n\tpadding-right: .3em;\n\tmin-width: 1.4em;\n\tline-height: 1.5;\n\tvertical-align: middle;\n\tcounter-increment: listnumbering;\n\tcontent: counter(listnumbering) \".\";\n}\nol.ui-listview > li.ui-field-contain:before {\n\tcontent: none;\n\tdisplay: none;\n}\nol.ui-listview > li h1:first-child,\nol.ui-listview > li h2:first-child,\nol.ui-listview > li h3:first-child,\nol.ui-listview > li h4:first-child,\nol.ui-listview > li h5:first-child,\nol.ui-listview > li h6:first-child,\nol.ui-listview > li p:first-child,\nol.ui-listview > li img:first-child + * {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\nol.ui-listview > li h1:first-child ~ *,\nol.ui-listview > li h2:first-child ~ *,\nol.ui-listview > li h3:first-child ~ *,\nol.ui-listview > li h4:first-child ~ *,\nol.ui-listview > li h5:first-child ~ *,\nol.ui-listview > li h6:first-child ~ *,\nol.ui-listview > li p:first-child ~ *,\nol.ui-listview > li img:first-child + * ~ * {\n\tmargin-top: 0;\n\ttext-indent: 2.04em; /* (1.4em + .3em) * .9em / .75em */\n}\nhtml .ui-filterable + .ui-listview,\nhtml .ui-filterable.ui-listview {\n\tmargin-top: .5em;\n}\n.ui-collapsible-content > form.ui-filterable {\n\tmargin-top: -.5em;\n}\n.ui-collapsible-content > .ui-input-search.ui-filterable {\n\tmargin-top: 0;\n}\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 1px;\n}\ndiv.ui-slider {\n\theight: 30px;\n\tmargin: .5em 0;\n\tpadding: 0;\n\t-ms-touch-action: pan-y pinch-zoom double-tap-zoom;\n}\ndiv.ui-slider:before,\ndiv.ui-slider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\ndiv.ui-slider:after {\n\tclear: both;\n}\ninput.ui-slider-input {\n\tdisplay: block;\n\tfloat: left;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tmargin: 0;\n\tpadding: 4px;\n\twidth: 40px;\n\theight: 20px;\n\tline-height: 20px;\n\tborder-width: 1px;\n\tborder-style: solid;\n\toutline: 0;\n\ttext-align: center;\n\tvertical-align: text-bottom;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tappearance: none;\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-slider-input::-webkit-outer-spin-button,\n.ui-slider-input::-webkit-inner-spin-button {\n\t-webkit-appearance: none;\n\tmargin: 0;\n}\n.ui-slider-track {\n\tposition: relative;\n\toverflow: visible;\n\tborder-width: 1px;\n\tborder-style: solid;\n\theight: 15px;\n\tmargin: 0 15px 0 68px;\n\ttop: 6px;\n}\n.ui-slider-track.ui-mini {\n\theight: 12px;\n\ttop: 8px;\n}\n.ui-slider-track .ui-slider-bg {\n\theight: 100%;\n}\n/* High level of specificity to override button margins in grids */\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tposition: absolute;\n\tz-index: 1;\n\ttop: 50%;\n\twidth: 28px;\n\theight: 28px;\n\tmargin: -15px 0 0 -15px;\n\toutline: 0;\n\tpadding: 0;\n}\n.ui-slider-track.ui-mini .ui-slider-handle {\n\theight: 14px;\n\twidth: 14px;\n\tmargin: -8px 0 0 -8px;\n}\nselect.ui-slider-switch {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\ndiv.ui-slider-switch {\n\tdisplay: inline-block;\n\theight: 32px;\n\twidth: 5.8em;\n\ttop: 0;\n}\n/* reset the clearfix */\ndiv.ui-slider-switch:before,\ndiv.ui-slider-switch:after {\n\tdisplay: none;\n\tclear: none;\n}\ndiv.ui-slider-switch.ui-mini {\n\theight: 29px;\n\ttop: 0;\n}\n.ui-slider-inneroffset {\n\tmargin: 0 16px;\n\tposition: relative;\n\tz-index: 1;\n}\n.ui-slider-switch.ui-mini .ui-slider-inneroffset {\n\tmargin: 0 15px 0 14px;\n}\n.ui-slider-switch .ui-btn.ui-slider-handle {\n\tmargin: 1px 0 0 -15px;\n}\n.ui-slider-switch.ui-mini .ui-slider-handle {\n\twidth: 25px;\n\theight: 25px;\n\tmargin: 1px 0 0 -13px;\n\tpadding: 0;\n}\n.ui-slider-handle-snapping {\n\t-webkit-transition: left 70ms linear;\n\t-moz-transition: left 70ms linear;\n\ttransition: left 70ms linear;\n}\n.ui-slider-switch .ui-slider-label {\n\tposition: absolute;\n\ttext-align: center;\n\twidth: 100%;\n\toverflow: hidden;\n\tfont-size: 16px;\n\ttop: 0;\n\tline-height: 2;\n\tmin-height: 100%;\n\twhite-space: nowrap;\n\tcursor: pointer;\n}\n.ui-slider-switch.ui-mini .ui-slider-label {\n\tfont-size: 14px;\n}\n.ui-slider-switch .ui-slider-label-a {\n\tz-index: 1;\n\tleft: 0;\n\ttext-indent: -1.5em;\n}\n.ui-slider-switch .ui-slider-label-b {\n\tz-index: 0;\n\tright: 0;\n\ttext-indent: 1.5em;\n}\n/* The corner radii for ui-slider-switch/track can be specified in theme CSS. The bg and handle inherits. */\n.ui-slider-track .ui-slider-bg,\n.ui-slider-switch .ui-slider-label,\n.ui-slider-switch .ui-slider-inneroffset,\n.ui-slider-handle {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-field-contain div.ui-slider-switch {\n\tmargin: 0;\n}\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-field-contain div.ui-slider-switch,\n.ui-field-contain.ui-hide-label div.ui-slider-switch,\nhtml .ui-popup .ui-field-contain div.ui-slider-switch {\n\tdisplay: inline-block;\n\twidth: 5.8em;\n}\n/* slider tooltip\n-----------------------------------------------------------------------------------------------------------*/\n.ui-slider-popup {\n\twidth: 64px;\n\theight: 64px;\n\tfont-size: 36px;\n\tpadding-top: 14px;\n\topacity: 0.8;\n}\n.ui-slider-popup {\n\tposition: absolute !important;\n\ttext-align: center;\n\tz-index: 100;\n}\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tfont-size: .9em;\n\tline-height: 30px;\n}\n.ui-rangeslider {\n\tmargin: .5em 0;\n}\n.ui-rangeslider:before,\n.ui-rangeslider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-rangeslider:after {\n\tclear: both;\n}\n.ui-rangeslider .ui-slider-input.ui-rangeslider-last {\n\tfloat: right;\n}\n.ui-rangeslider .ui-rangeslider-sliders {\n\tposition: relative;\n\toverflow: visible;\n\theight: 30px;\n\tmargin: 0 68px;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track {\n\tposition: absolute;\n\ttop: 6px;\n\tright: 0;\n\tleft: 0;\n\tmargin: 0;\n}\n.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track {\n\ttop: 8px;\n}\n.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg {\n\tdisplay: none;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\tbackground-color: transparent;\n\tbackground: none;\n\tborder-width: 0;\n\theight: 0;\n}\n/* this makes ie6 and ie7 set height to 0 to fix z-index problem */\nhtml >/**/body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 15px;\n\tborder-width: 1px;\n}\nhtml >/**/body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 12px;\n}\n/* Hide the second label (the first is moved outside the div) */\ndiv.ui-rangeslider label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-field-contain .ui-rangeslider input.ui-slider-input,\n.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,\n.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,\n.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders {\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n}\n.ui-input-text,\n.ui-input-search {\n\tmargin: .5em 0;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-mini {\n\tmargin: .446em;\n}\n.ui-input-text input,\n.ui-input-search input,\ntextarea.ui-input-text {\n\tpadding: .4em;\n\tline-height: 1.4em;\n\tdisplay: block;\n\twidth: 100%;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\toutline: 0;\n}\n.ui-input-text input,\n.ui-input-search input {\n\tmargin: 0;\n\tmin-height: 2.2em;\n\ttext-align: left; /* Opera aligns type=\"date\" right by default */\n\tborder: 0;\n\tbackground: transparent none;\n\t-webkit-appearance: none;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\ntextarea.ui-input-text {\n\toverflow: auto;\n\tresize: vertical;\n}\n.ui-mini .ui-input-text input,\n.ui-mini .ui-input-search input,\n.ui-input-text.ui-mini input,\n.ui-input-search.ui-mini input,\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tfont-size: 14px;\n}\n/* Same margin for mini textareas as other mini sized widgets (12.5/14 * 0.5em) */\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tmargin: .446em 0;\n}\n.ui-input-has-clear,\n.ui-input-search {\n\tposition: relative;\n}\n/* Padding on the div instead of input because of browser spinners etc. */\n.ui-input-has-clear {\n\tpadding-right: 2.375em;\n}\n.ui-mini.ui-input-has-clear {\n\tpadding-right: 2.923em;\n}\n.ui-input-has-clear input {\n\tpadding-right: 0;\n\t/* Autofill on Chrome has bg color so we unset corners right as well. */\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n/* Search icon */\n.ui-input-search input {\n\tpadding-left: 1.75em;\n}\n.ui-input-search:after {\n\tposition: absolute;\n\tleft: .3125em;\n\ttop: 50%;\n\tmargin-top: -7px;\n\tcontent: \"\";\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\twidth: 14px;\n\theight: 14px;\n\tfilter: Alpha(Opacity=50);\n\topacity: .5;\n}\n.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,\n.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear {\n\tposition: absolute;\n\tright: 0;\n\ttop: 50%;\n\tmargin: -14px .3125em 0;\n\tborder: 0;\n\tbackground-color: transparent;\n}\n.ui-input-search .ui-input-clear-hidden,\n.ui-input-text .ui-input-clear-hidden {\n\tdisplay: none;\n}\n/* Resolves issue #5166: Added to support issue introduced in Firefox 15. We can likely remove this in the future. */\n.ui-input-text input::-moz-placeholder,\n.ui-input-search input::-moz-placeholder,\ntextarea.ui-input-text::-moz-placeholder {\n\tcolor: #aaa;\n}\n/* Same for IE10 */\n.ui-input-text input:-ms-input-placeholder,\n.ui-input-search input:-ms-input-placeholder,\ntextarea.ui-input-text:-ms-input-placeholder {\n\tcolor: #aaa;\n}\n/* Resolves issue #5131: Width of textinput depends on its type,\nfor Android 4.1 */\n.ui-input-text input[type=number]::-webkit-outer-spin-button {\n\tmargin: 0;\n}\n/* Resolves issue #5756: Textinput in IE10 has a default clear button */\n.ui-input-text input::-ms-clear,\n.ui-input-search input::-ms-clear {\n\tdisplay: none;\n}\n.ui-input-text input:focus,\n.ui-input-search input:focus {\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n\tbox-shadow: none;\n}\ntextarea.ui-input-text.ui-textinput-autogrow {\n\toverflow: hidden;\n}\n.ui-textinput-autogrow-resize {\n\t-webkit-transition: height 0.25s;\n\t-o-transition: height 0.25s;\n\t-moz-transition: height 0.25s;\n\ttransition: height 0.25s;\n}\n.ui-flipswitch {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\twidth: 5.875em; /* Override this and padding-left in next rule if you use labels other than \"on/off\" and need more space */\n\theight: 1.875em;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tmargin: .5em 0;\n\toverflow: hidden;\n\t-webkit-transition-property: padding, width, background-color, color, border-color;\n\t-moz-transition-property: padding, width, background-color, color, border-color;\n\t-o-transition-property: padding, width, background-color, color, border-color;\n\ttransition-property: padding, width, background-color, color, border-color;\n\t-webkit-transition-duration: 100ms;\n\t-moz-transition-duration: 100ms;\n\t-o-transition-duration: 100ms;\n\ttransition-duration: 100ms;\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\tcursor: pointer;\n}\n.ui-flipswitch.ui-flipswitch-active {\n\tpadding-left: 4em;  /* Override this and width in previous rule if you use labels other than \"on/off\" and need more space */\n\twidth: 1.875em;\n}\n.ui-flipswitch-input {\n\tposition: absolute;\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n\tborder: 0;\n\toutline: 0;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on,\n.ui-flipswitch .ui-flipswitch-off {\n\tfloat: left;\n\theight: 1.75em;\n\tmargin: .0625em;\n\tline-height: 1.65em;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on {\n\twidth: 1.75em;\n\tpadding: 0;\n\ttext-indent: -2.6em; /* Override this to center text if you use a label other than \"on\" */\n\ttext-align: left;\n\tborder-width: 1px;\n\tborder-style: solid;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-radius: inherit;\n\toverflow: visible;\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n.ui-flipswitch .ui-flipswitch-off {\n\tpadding: 1px;\n\ttext-indent: 1em; /* Override this to center text if you use a label other than \"off\" */\n}\n/* Override field container CSS to prevent the flipswitch from becomming full width */\nhtml .ui-field-contain > label + .ui-flipswitch,\nhtml .ui-popup .ui-field-contain > label + .ui-flipswitch {\n\tdisplay: inline-block;\n\twidth: 5.875em; /* If you override the width for .ui-flipswitch you should repeat the same value here */\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-field-contain .ui-flipswitch.ui-flipswitch-active,\n.ui-popup .ui-field-contain .ui-flipswitch.ui-flipswitch-active {\n\twidth: 1.875em;\n}\n.ui-table {\n\tborder: 0;\n\tborder-collapse: collapse;\n\tpadding: 0;\n\twidth: 100%;\n}\n.ui-table th,\n.ui-table td {\n\tline-height: 1.5em;\n\ttext-align: left;\n\tpadding: .4em .5em;\n\tvertical-align:top;\n}\n.ui-table th .ui-btn,\n.ui-table td .ui-btn {\n\tline-height: normal;\n}\n.ui-table th {\n\tfont-weight: bold;\n}\n.ui-table caption {\n\ttext-align: left;\n\tmargin-bottom: 1.4em;\n\topacity: .5;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-columntoggle-btn {\n\tfloat: right;\n\tmargin-bottom: .8em;\n}\n/* Remove top/bottom margins around the fieldcontain on check list */\n.ui-table-columntoggle-popup fieldset {\n\tmargin:0;\n}\n.ui-table-columntoggle {\n\tclear: both;\n}\n/* Hide all prioritized columns by default */\n@media only all {\n\tth.ui-table-priority-6,\n\ttd.ui-table-priority-6,\n\tth.ui-table-priority-5,\n\ttd.ui-table-priority-5,\n\tth.ui-table-priority-4,\n\ttd.ui-table-priority-4,\n\tth.ui-table-priority-3,\n\ttd.ui-table-priority-3,\n\tth.ui-table-priority-2,\n\ttd.ui-table-priority-2,\n\tth.ui-table-priority-1,\n\ttd.ui-table-priority-1 {\n\t\tdisplay: none;\n\t}\n}\n/* Preset breakpoints if \".ui-responsive\" class added to table */\n/* Show priority 1 at 320px (20em x 16px) */\n@media screen and (min-width: 20em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-1 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 2 at 480px (30em x 16px) */\n@media screen and (min-width: 30em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-2 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 3 at 640px (40em x 16px) */\n@media screen and (min-width: 40em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-3 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 4 at 800px (50em x 16px) */\n@media screen and (min-width: 50em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-4 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 5 at 960px (60em x 16px) */\n@media screen and (min-width: 60em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-5 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 6 at 1,120px (70em x 16px) */\n@media screen and (min-width: 70em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-6 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Unchecked manually: Always hide */\n.ui-table-columntoggle th.ui-table-cell-hidden,\n.ui-table-columntoggle td.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden {\n\tdisplay: none;\n}\n/* Checked manually: Always show */\n.ui-table-columntoggle th.ui-table-cell-visible,\n.ui-table-columntoggle td.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible {\n\tdisplay: table-cell;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-reflow td .ui-table-cell-label,\n.ui-table-reflow th .ui-table-cell-label { \n\tdisplay: none;\n}\n/* Mobile first styles: Begin with the stacked presentation at narrow widths */ \n@media only all {\n\t/* Hide the table headers */ \n\t.ui-table-reflow thead td, \n\t.ui-table-reflow thead th {\n\t\tdisplay: none;\n\t}\n\t/* Show the table cells as a block level element */ \n\t.ui-table-reflow td,\n\t.ui-table-reflow th { \n\t\ttext-align: left;\n\t\tdisplay: block;\n\t}\n\t/* Add a fair amount of top margin to visually separate each row when stacked */  \n\t.ui-table-reflow tbody th {\n\t\tmargin-top: 3em;\n\t}\n\t/* Make the label elements a percentage width */ \n\t.ui-table-reflow td .ui-table-cell-label,\n\t.ui-table-reflow th .ui-table-cell-label { \n\t\tpadding: .4em; \n\t\tmin-width: 30%; \n\t\tdisplay: inline-block;\n\t\tmargin: -.4em 1em -.4em -.4em;\n\t}\n\t/* For grouped headers, have a different style to visually separate the levels by classing the first label in each col group */ \n\t.ui-table-reflow th .ui-table-cell-label-top,\n\t.ui-table-reflow td .ui-table-cell-label-top {\n\t\tdisplay: block;\n\t\tpadding: .4em 0;\n\t\tmargin: .4em 0;\n\t\ttext-transform: uppercase;\n\t\tfont-size: .9em;\n\t\tfont-weight: normal;\n\t}\n}\n/* Breakpoint to show as a standard table at 560px (35em x 16px) or wider */ \n@media ( min-width: 35em ) {\n\t/* Show the table header rows */ \n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th,\n\t.ui-table-reflow.ui-responsive tbody th,\n\t.ui-table-reflow.ui-responsive tbody td,\n\t.ui-table-reflow.ui-responsive thead td,\n\t.ui-table-reflow.ui-responsive thead th {\n\t\tdisplay: table-cell;\n\t\tmargin: 0;\n\t}\n\t/* Hide the labels in each cell */ \n\t.ui-table-reflow.ui-responsive td .ui-table-cell-label,\n\t.ui-table-reflow.ui-responsive th .ui-table-cell-label { \n\t\tdisplay: none;\n\t}\n}\n/* Hack to make IE9 and WP7.5 treat cells like block level elements, scoped to ui-responsive class */ \n/* Applied in a max-width media query up to the table layout breakpoint so we don't need to negate this*/ \n@media ( max-width: 35em ) {\n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th {\n\t\twidth: 100%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t\tfloat: left;\n\t\tclear: left;\n\t}\n}\n/* Panel */\n.ui-panel {\n\twidth: 17em;\n\tmin-height: 100%;\n\tmax-height: none;\n\tborder-width: 0;\n\tposition: absolute;\n\ttop: 0;\n\tdisplay: block;\n}\n.ui-panel-closed {\n\twidth: 0;\n\tmax-height: 100%;\n\toverflow: hidden;\n\tvisibility: hidden;\n\tleft: 0;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-panel-fixed {\n\tposition: fixed;\n\tbottom: -1px; /* Fixes gap on Chrome for Android */\n\tpadding-bottom: 1px;\n}\n.ui-panel-display-reveal {\n\tz-index: 1;\n}\n.ui-panel-display-push {\n\tz-index: 999;\n}\n.ui-panel-display-overlay {\n\tz-index: 1001; /* Fixed toolbars have z-index 1000 */\n}\n.ui-panel-inner {\n\tpadding: 1em;\n}\n/* Container, page and wrapper */\n.ui-panel-page-container {\n\toverflow-x: visible;\n}\n.ui-panel-page-container-themed .ui-page-active {\n\tbackground: none;\n}\n.ui-panel-wrapper {\n\tposition: relative;\n\tmin-height: inherit;\n\tborder: 0;\n\toverflow-x: hidden;\n\tz-index: 999;\n}\n/* Fixed toolbars */\n.ui-panel-fixed-toolbar {\n\toverflow-x: hidden;\n}\n/* Dismiss */\n.ui-panel-dismiss {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\theight: 100%;\n\tz-index: 1002;\n\tdisplay: none;\n}\n.ui-panel-dismiss-open {\n\tdisplay: block;\n}\n/* Animate class is added to panel, wrapper and fixed toolbars */\n.ui-panel-animate {\n\t-webkit-transition: -webkit-transform 300ms ease;\n\t-webkit-transition-duration: 300ms;\n\t-moz-transition: -moz-transform 300ms ease;\n\ttransition: transform 300ms ease;\n}\n/* Fix for Windows Phone issue #6349: unset the transition for transforms in case of fixed toolbars. */\n@media screen and ( max-device-width: 768px ) {\n\t.ui-page-header-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-page-footer-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: none;\n\t}\n\t/* We need a transitionend event ... */\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: -ms-transform 1ms;\n\t\t-ms-transform: rotate(0deg);\n\t}\n}\n/* Hardware acceleration for smoother transitions on WebKit browsers */\n.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal) {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translate3d(0,0,0);\n}\n/* Panel positioning (for overlay and push) */\n/* Panel left closed */\n.ui-panel-position-left {\n\tleft: -17em;\n}\n/* Panel left closed animated */\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-push {\n\tleft: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Panel left open */\n.ui-panel-position-left.ui-panel-display-reveal, /* Unset \"panel left closed\" for reveal */\n.ui-panel-open.ui-panel-position-left {\n\tleft: 0;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Panel right closed */\n.ui-panel-position-right {\n\tright: -17em;\n}\n/* Panel right closed animated */\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-push {\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-position-right.ui-panel-display-reveal, /* Unset \"panel right closed\" for reveal */\n.ui-panel-position-right.ui-panel-open {\n\tright: 0;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Wrapper and fixed toolbars positioning (for reveal and push) */\n/* Panel left open */\n.ui-panel-page-content-position-left {\n\tleft: 17em;\n\tright: -17em;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-page-content-position-left {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-page-content-position-right {\n\tleft: -17em;\n\tright: 17em;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-page-content-position-right {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Dismiss model open */\n.ui-panel-dismiss-open.ui-panel-dismiss-position-left {\n\tleft: 17em;\n}\n.ui-panel-dismiss-open.ui-panel-dismiss-position-right {\n\tright: 17em;\n}\n/* Shadows and borders */\n.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-display-overlay {\n\t-webkit-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-overlay {\n\t-webkit-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-panel-page-content-position-left.ui-panel-page-content-display-push {\n\tmargin-left: 1px;\n\twidth: auto;\n}\n.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\tborder-left-width: 1px;\n\tmargin-left: -1px;\n}\n.ui-panel-page-content-position-right.ui-panel-page-content-display-push {\n\tmargin-right: 1px;\n\twidth: auto;\n}\n/* Responsive: wrap on wide viewports once open */\n@media (min-width:55em) {\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left {\n\t\tmargin-right: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right {\n\t\tmargin-left: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open {\n\t\twidth: auto;\t\n\t}\n\t.ui-responsive-panel .ui-panel-dismiss-display-push,\n\t.ui-responsive-panel.ui-page-active ~ .ui-panel-dismiss-display-push {\n\t\tdisplay: none;\n\t}\n}\n.ui-tabs {\n\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n\tpadding: .2em;\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile-1.4.5.js",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n(function ( root, doc, factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine( [ \"jquery\" ], function ( $ ) {\n\t\t\tfactory( $, root, doc );\n\t\t\treturn $.mobile;\n\t\t});\n\t} else {\n\t\t// Browser globals\n\t\tfactory( root.jQuery, root, doc );\n\t}\n}( this, document, function ( jQuery, window, document, undefined ) {\n(function( $ ) {\n\t$.mobile = {};\n}( jQuery ));\n\n/*!\n * jQuery UI Core c0ab71056b936627e8a7821f03c044aec6280a40\n * http://jqueryui.com\n *\n * Copyright 2013 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/category/ui-core/\n */\n(function( $, undefined ) {\n\nvar uuid = 0,\n\truniqueId = /^ui-id-\\d+$/;\n\n// $.ui might exist from components with no dependencies, e.g., $.ui.position\n$.ui = $.ui || {};\n\n$.extend( $.ui, {\n\tversion: \"c0ab71056b936627e8a7821f03c044aec6280a40\",\n\n\tkeyCode: {\n\t\tBACKSPACE: 8,\n\t\tCOMMA: 188,\n\t\tDELETE: 46,\n\t\tDOWN: 40,\n\t\tEND: 35,\n\t\tENTER: 13,\n\t\tESCAPE: 27,\n\t\tHOME: 36,\n\t\tLEFT: 37,\n\t\tPAGE_DOWN: 34,\n\t\tPAGE_UP: 33,\n\t\tPERIOD: 190,\n\t\tRIGHT: 39,\n\t\tSPACE: 32,\n\t\tTAB: 9,\n\t\tUP: 38\n\t}\n});\n\n// plugins\n$.fn.extend({\n\tfocus: (function( orig ) {\n\t\treturn function( delay, fn ) {\n\t\t\treturn typeof delay === \"number\" ?\n\t\t\t\tthis.each(function() {\n\t\t\t\t\tvar elem = this;\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t$( elem ).focus();\n\t\t\t\t\t\tif ( fn ) {\n\t\t\t\t\t\t\tfn.call( elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, delay );\n\t\t\t\t}) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t})( $.fn.focus ),\n\n\tscrollParent: function() {\n\t\tvar scrollParent;\n\t\tif (($.ui.ie && (/(static|relative)/).test(this.css(\"position\"))) || (/absolute/).test(this.css(\"position\"))) {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(relative|absolute|fixed)/).test($.css(this,\"position\")) && (/(auto|scroll)/).test($.css(this,\"overflow\")+$.css(this,\"overflow-y\")+$.css(this,\"overflow-x\"));\n\t\t\t}).eq(0);\n\t\t} else {\n\t\t\tscrollParent = this.parents().filter(function() {\n\t\t\t\treturn (/(auto|scroll)/).test($.css(this,\"overflow\")+$.css(this,\"overflow-y\")+$.css(this,\"overflow-x\"));\n\t\t\t}).eq(0);\n\t\t}\n\n\t\treturn ( /fixed/ ).test( this.css( \"position\") ) || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;\n\t},\n\n\tuniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( !this.id ) {\n\t\t\t\tthis.id = \"ui-id-\" + (++uuid);\n\t\t\t}\n\t\t});\n\t},\n\n\tremoveUniqueId: function() {\n\t\treturn this.each(function() {\n\t\t\tif ( runiqueId.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t});\n\t}\n});\n\n// selectors\nfunction focusable( element, isTabIndexNotNaN ) {\n\tvar map, mapName, img,\n\t\tnodeName = element.nodeName.toLowerCase();\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap=#\" + mapName + \"]\" )[0];\n\t\treturn !!img && visible( img );\n\t}\n\treturn ( /input|select|textarea|button|object/.test( nodeName ) ?\n\t\t!element.disabled :\n\t\t\"a\" === nodeName ?\n\t\t\telement.href || isTabIndexNotNaN :\n\t\t\tisTabIndexNotNaN) &&\n\t\t// the element and all of its ancestors must be visible\n\t\tvisible( element );\n}\n\nfunction visible( element ) {\n\treturn $.expr.filters.visible( element ) &&\n\t\t!$( element ).parents().addBack().filter(function() {\n\t\t\treturn $.css( this, \"visibility\" ) === \"hidden\";\n\t\t}).length;\n}\n\n$.extend( $.expr[ \":\" ], {\n\tdata: $.expr.createPseudo ?\n\t\t$.expr.createPseudo(function( dataName ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn !!$.data( elem, dataName );\n\t\t\t};\n\t\t}) :\n\t\t// support: jQuery <1.8\n\t\tfunction( elem, i, match ) {\n\t\t\treturn !!$.data( elem, match[ 3 ] );\n\t\t},\n\n\tfocusable: function( element ) {\n\t\treturn focusable( element, !isNaN( $.attr( element, \"tabindex\" ) ) );\n\t},\n\n\ttabbable: function( element ) {\n\t\tvar tabIndex = $.attr( element, \"tabindex\" ),\n\t\t\tisTabIndexNaN = isNaN( tabIndex );\n\t\treturn ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );\n\t}\n});\n\n// support: jQuery <1.8\nif ( !$( \"<a>\" ).outerWidth( 1 ).jquery ) {\n\t$.each( [ \"Width\", \"Height\" ], function( i, name ) {\n\t\tvar side = name === \"Width\" ? [ \"Left\", \"Right\" ] : [ \"Top\", \"Bottom\" ],\n\t\t\ttype = name.toLowerCase(),\n\t\t\torig = {\n\t\t\t\tinnerWidth: $.fn.innerWidth,\n\t\t\t\tinnerHeight: $.fn.innerHeight,\n\t\t\t\touterWidth: $.fn.outerWidth,\n\t\t\t\touterHeight: $.fn.outerHeight\n\t\t\t};\n\n\t\tfunction reduce( elem, size, border, margin ) {\n\t\t\t$.each( side, function() {\n\t\t\t\tsize -= parseFloat( $.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\tif ( border ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( margin ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"margin\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn size;\n\t\t}\n\n\t\t$.fn[ \"inner\" + name ] = function( size ) {\n\t\t\tif ( size === undefined ) {\n\t\t\t\treturn orig[ \"inner\" + name ].call( this );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this ).css( type, reduce( this, size ) + \"px\" );\n\t\t\t});\n\t\t};\n\n\t\t$.fn[ \"outer\" + name] = function( size, margin ) {\n\t\t\tif ( typeof size !== \"number\" ) {\n\t\t\t\treturn orig[ \"outer\" + name ].call( this, size );\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\t$( this).css( type, reduce( this, size, true, margin ) + \"px\" );\n\t\t\t});\n\t\t};\n\t});\n}\n\n// support: jQuery <1.8\nif ( !$.fn.addBack ) {\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)\nif ( $( \"<a>\" ).data( \"a-b\", \"a\" ).removeData( \"a-b\" ).data( \"a-b\" ) ) {\n\t$.fn.removeData = (function( removeData ) {\n\t\treturn function( key ) {\n\t\t\tif ( arguments.length ) {\n\t\t\t\treturn removeData.call( this, $.camelCase( key ) );\n\t\t\t} else {\n\t\t\t\treturn removeData.call( this );\n\t\t\t}\n\t\t};\n\t})( $.fn.removeData );\n}\n\n\n\n\n\n// deprecated\n$.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n\n$.support.selectstart = \"onselectstart\" in document.createElement( \"div\" );\n$.fn.extend({\n\tdisableSelection: function() {\n\t\treturn this.bind( ( $.support.selectstart ? \"selectstart\" : \"mousedown\" ) +\n\t\t\t\".ui-disableSelection\", function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t});\n\t},\n\n\tenableSelection: function() {\n\t\treturn this.unbind( \".ui-disableSelection\" );\n\t},\n\n\tzIndex: function( zIndex ) {\n\t\tif ( zIndex !== undefined ) {\n\t\t\treturn this.css( \"zIndex\", zIndex );\n\t\t}\n\n\t\tif ( this.length ) {\n\t\t\tvar elem = $( this[ 0 ] ), position, value;\n\t\t\twhile ( elem.length && elem[ 0 ] !== document ) {\n\t\t\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n\t\t\t\t// This makes behavior of this function consistent across browsers\n\t\t\t\t// WebKit always returns auto if the element is positioned\n\t\t\t\tposition = elem.css( \"position\" );\n\t\t\t\tif ( position === \"absolute\" || position === \"relative\" || position === \"fixed\" ) {\n\t\t\t\t\t// IE returns 0 when zIndex is not specified\n\t\t\t\t\t// other browsers return a string\n\t\t\t\t\t// we ignore the case of nested elements with an explicit value of 0\n\t\t\t\t\t// <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n\t\t\t\t\tvalue = parseInt( elem.css( \"zIndex\" ), 10 );\n\t\t\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telem = elem.parent();\n\t\t\t}\n\t\t}\n\n\t\treturn 0;\n\t}\n});\n\n// $.ui.plugin is deprecated. Use $.widget() extensions instead.\n$.ui.plugin = {\n\tadd: function( module, option, set ) {\n\t\tvar i,\n\t\t\tproto = $.ui[ module ].prototype;\n\t\tfor ( i in set ) {\n\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n\t\t}\n\t},\n\tcall: function( instance, name, args, allowDisconnected ) {\n\t\tvar i,\n\t\t\tset = instance.plugins[ name ];\n\n\t\tif ( !set ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( i = 0; i < set.length; i++ ) {\n\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n\t\t\t}\n\t\t}\n\t}\n};\n\n})( jQuery );\n\n(function( $, window, undefined ) {\n\n\t// Subtract the height of external toolbars from the page height, if the page does not have\n\t// internal toolbars of the same type. We take care to use the widget options if we find a\n\t// widget instance and the element's data-attributes otherwise.\n\tvar compensateToolbars = function( page, desiredHeight ) {\n\t\tvar pageParent = page.parent(),\n\t\t\ttoolbarsAffectingHeight = [],\n\n\t\t\t// We use this function to filter fixed toolbars with option updatePagePadding set to\n\t\t\t// true (which is the default) from our height subtraction, because fixed toolbars with\n\t\t\t// option updatePagePadding set to true compensate for their presence by adding padding\n\t\t\t// to the active page. We want to avoid double-counting by also subtracting their\n\t\t\t// height from the desired page height.\n\t\t\tnoPadders = function() {\n\t\t\t\tvar theElement = $( this ),\n\t\t\t\t\twidgetOptions = $.mobile.toolbar && theElement.data( \"mobile-toolbar\" ) ?\n\t\t\t\t\t\ttheElement.toolbar( \"option\" ) : {\n\t\t\t\t\t\t\tposition: theElement.attr( \"data-\" + $.mobile.ns + \"position\" ),\n\t\t\t\t\t\t\tupdatePagePadding: ( theElement.attr( \"data-\" + $.mobile.ns +\n\t\t\t\t\t\t\t\t\"update-page-padding\" ) !== false )\n\t\t\t\t\t\t};\n\n\t\t\t\treturn !( widgetOptions.position === \"fixed\" &&\n\t\t\t\t\twidgetOptions.updatePagePadding === true );\n\t\t\t},\n\t\t\texternalHeaders = pageParent.children( \":jqmData(role='header')\" ).filter( noPadders ),\n\t\t\tinternalHeaders = page.children( \":jqmData(role='header')\" ),\n\t\t\texternalFooters = pageParent.children( \":jqmData(role='footer')\" ).filter( noPadders ),\n\t\t\tinternalFooters = page.children( \":jqmData(role='footer')\" );\n\n\t\t// If we have no internal headers, but we do have external headers, then their height\n\t\t// reduces the page height\n\t\tif ( internalHeaders.length === 0 && externalHeaders.length > 0 ) {\n\t\t\ttoolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalHeaders.toArray() );\n\t\t}\n\n\t\t// If we have no internal footers, but we do have external footers, then their height\n\t\t// reduces the page height\n\t\tif ( internalFooters.length === 0 && externalFooters.length > 0 ) {\n\t\t\ttoolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalFooters.toArray() );\n\t\t}\n\n\t\t$.each( toolbarsAffectingHeight, function( index, value ) {\n\t\t\tdesiredHeight -= $( value ).outerHeight();\n\t\t});\n\n\t\t// Height must be at least zero\n\t\treturn Math.max( 0, desiredHeight );\n\t};\n\n\t$.extend( $.mobile, {\n\t\t// define the window and the document objects\n\t\twindow: $( window ),\n\t\tdocument: $( document ),\n\n\t\t// TODO: Remove and use $.ui.keyCode directly\n\t\tkeyCode: $.ui.keyCode,\n\n\t\t// Place to store various widget extensions\n\t\tbehaviors: {},\n\n\t\t// Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value\n\t\tsilentScroll: function( ypos ) {\n\t\t\tif ( $.type( ypos ) !== \"number\" ) {\n\t\t\t\typos = $.mobile.defaultHomeScroll;\n\t\t\t}\n\n\t\t\t// prevent scrollstart and scrollstop events\n\t\t\t$.event.special.scrollstart.enabled = false;\n\n\t\t\tsetTimeout(function() {\n\t\t\t\twindow.scrollTo( 0, ypos );\n\t\t\t\t$.mobile.document.trigger( \"silentscroll\", { x: 0, y: ypos });\n\t\t\t}, 20 );\n\n\t\t\tsetTimeout(function() {\n\t\t\t\t$.event.special.scrollstart.enabled = true;\n\t\t\t}, 150 );\n\t\t},\n\n\t\tgetClosestBaseUrl: function( ele )\t{\n\t\t\t// Find the closest page and extract out its url.\n\t\t\tvar url = $( ele ).closest( \".ui-page\" ).jqmData( \"url\" ),\n\t\t\t\tbase = $.mobile.path.documentBase.hrefNoHash;\n\n\t\t\tif ( !$.mobile.dynamicBaseEnabled || !url || !$.mobile.path.isPath( url ) ) {\n\t\t\t\turl = base;\n\t\t\t}\n\n\t\t\treturn $.mobile.path.makeUrlAbsolute( url, base );\n\t\t},\n\t\tremoveActiveLinkClass: function( forceRemoval ) {\n\t\t\tif ( !!$.mobile.activeClickedLink &&\n\t\t\t\t( !$.mobile.activeClickedLink.closest( \".\" + $.mobile.activePageClass ).length ||\n\t\t\t\t\tforceRemoval ) ) {\n\n\t\t\t\t$.mobile.activeClickedLink.removeClass( $.mobile.activeBtnClass );\n\t\t\t}\n\t\t\t$.mobile.activeClickedLink = null;\n\t\t},\n\n\t\t// DEPRECATED in 1.4\n\t\t// Find the closest parent with a theme class on it. Note that\n\t\t// we are not using $.fn.closest() on purpose here because this\n\t\t// method gets called quite a bit and we need it to be as fast\n\t\t// as possible.\n\t\tgetInheritedTheme: function( el, defaultTheme ) {\n\t\t\tvar e = el[ 0 ],\n\t\t\t\tltr = \"\",\n\t\t\t\tre = /ui-(bar|body|overlay)-([a-z])\\b/,\n\t\t\t\tc, m;\n\t\t\twhile ( e ) {\n\t\t\t\tc = e.className || \"\";\n\t\t\t\tif ( c && ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) {\n\t\t\t\t\t// We found a parent with a theme class\n\t\t\t\t\t// on it so bail from this loop.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\te = e.parentNode;\n\t\t\t}\n\t\t\t// Return the theme letter we found, if none, return the\n\t\t\t// specified default.\n\t\t\treturn ltr || defaultTheme || \"a\";\n\t\t},\n\n\t\tenhanceable: function( elements ) {\n\t\t\treturn this.haveParents( elements, \"enhance\" );\n\t\t},\n\n\t\thijackable: function( elements ) {\n\t\t\treturn this.haveParents( elements, \"ajax\" );\n\t\t},\n\n\t\thaveParents: function( elements, attr ) {\n\t\t\tif ( !$.mobile.ignoreContentEnabled ) {\n\t\t\t\treturn elements;\n\t\t\t}\n\n\t\t\tvar count = elements.length,\n\t\t\t\t$newSet = $(),\n\t\t\t\te, $element, excluded,\n\t\t\t\ti, c;\n\n\t\t\tfor ( i = 0; i < count; i++ ) {\n\t\t\t\t$element = elements.eq( i );\n\t\t\t\texcluded = false;\n\t\t\t\te = elements[ i ];\n\n\t\t\t\twhile ( e ) {\n\t\t\t\t\tc = e.getAttribute ? e.getAttribute( \"data-\" + $.mobile.ns + attr ) : \"\";\n\n\t\t\t\t\tif ( c === \"false\" ) {\n\t\t\t\t\t\texcluded = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\te = e.parentNode;\n\t\t\t\t}\n\n\t\t\t\tif ( !excluded ) {\n\t\t\t\t\t$newSet = $newSet.add( $element );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $newSet;\n\t\t},\n\n\t\tgetScreenHeight: function() {\n\t\t\t// Native innerHeight returns more accurate value for this across platforms,\n\t\t\t// jQuery version is here as a normalized fallback for platforms like Symbian\n\t\t\treturn window.innerHeight || $.mobile.window.height();\n\t\t},\n\n\t\t//simply set the active page's minimum height to screen height, depending on orientation\n\t\tresetActivePageHeight: function( height ) {\n\t\t\tvar page = $( \".\" + $.mobile.activePageClass ),\n\t\t\t\tpageHeight = page.height(),\n\t\t\t\tpageOuterHeight = page.outerHeight( true );\n\n\t\t\theight = compensateToolbars( page,\n\t\t\t\t( typeof height === \"number\" ) ? height : $.mobile.getScreenHeight() );\n\n\t\t\t// Remove any previous min-height setting\n\t\t\tpage.css( \"min-height\", \"\" );\n\n\t\t\t// Set the minimum height only if the height as determined by CSS is insufficient\n\t\t\tif ( page.height() < height ) {\n\t\t\t\tpage.css( \"min-height\", height - ( pageOuterHeight - pageHeight ) );\n\t\t\t}\n\t\t},\n\n\t\tloading: function() {\n\t\t\t// If this is the first call to this function, instantiate a loader widget\n\t\t\tvar loader = this.loading._widget || $( $.mobile.loader.prototype.defaultHtml ).loader(),\n\n\t\t\t\t// Call the appropriate method on the loader\n\t\t\t\treturnValue = loader.loader.apply( loader, arguments );\n\n\t\t\t// Make sure the loader is retained for future calls to this function.\n\t\t\tthis.loading._widget = loader;\n\n\t\t\treturn returnValue;\n\t\t}\n\t});\n\n\t$.addDependents = function( elem, newDependents ) {\n\t\tvar $elem = $( elem ),\n\t\t\tdependents = $elem.jqmData( \"dependents\" ) || $();\n\n\t\t$elem.jqmData( \"dependents\", $( dependents ).add( newDependents ) );\n\t};\n\n\t// plugins\n\t$.fn.extend({\n\t\tremoveWithDependents: function() {\n\t\t\t$.removeWithDependents( this );\n\t\t},\n\n\t\t// Enhance child elements\n\t\tenhanceWithin: function() {\n\t\t\tvar index,\n\t\t\t\twidgetElements = {},\n\t\t\t\tkeepNative = $.mobile.page.prototype.keepNativeSelector(),\n\t\t\t\tthat = this;\n\n\t\t\t// Add no js class to elements\n\t\t\tif ( $.mobile.nojs ) {\n\t\t\t\t$.mobile.nojs( this );\n\t\t\t}\n\n\t\t\t// Bind links for ajax nav\n\t\t\tif ( $.mobile.links ) {\n\t\t\t\t$.mobile.links( this );\n\t\t\t}\n\n\t\t\t// Degrade inputs for styleing\n\t\t\tif ( $.mobile.degradeInputsWithin ) {\n\t\t\t\t$.mobile.degradeInputsWithin( this );\n\t\t\t}\n\n\t\t\t// Run buttonmarkup\n\t\t\tif ( $.fn.buttonMarkup ) {\n\t\t\t\tthis.find( $.fn.buttonMarkup.initSelector ).not( keepNative )\n\t\t\t\t.jqmEnhanceable().buttonMarkup();\n\t\t\t}\n\n\t\t\t// Add classes for fieldContain\n\t\t\tif ( $.fn.fieldcontain ) {\n\t\t\t\tthis.find( \":jqmData(role='fieldcontain')\" ).not( keepNative )\n\t\t\t\t.jqmEnhanceable().fieldcontain();\n\t\t\t}\n\n\t\t\t// Enhance widgets\n\t\t\t$.each( $.mobile.widgets, function( name, constructor ) {\n\n\t\t\t\t// If initSelector not false find elements\n\t\t\t\tif ( constructor.initSelector ) {\n\n\t\t\t\t\t// Filter elements that should not be enhanced based on parents\n\t\t\t\t\tvar elements = $.mobile.enhanceable( that.find( constructor.initSelector ) );\n\n\t\t\t\t\t// If any matching elements remain filter ones with keepNativeSelector\n\t\t\t\t\tif ( elements.length > 0 ) {\n\n\t\t\t\t\t\t// $.mobile.page.prototype.keepNativeSelector is deprecated this is just for backcompat\n\t\t\t\t\t\t// Switch to $.mobile.keepNative in 1.5 which is just a value not a function\n\t\t\t\t\t\telements = elements.not( keepNative );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Enhance whatever is left\n\t\t\t\t\tif ( elements.length > 0 ) {\n\t\t\t\t\t\twidgetElements[ constructor.prototype.widgetName ] = elements;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tfor ( index in widgetElements ) {\n\t\t\t\twidgetElements[ index ][ index ]();\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\taddDependents: function( newDependents ) {\n\t\t\t$.addDependents( this, newDependents );\n\t\t},\n\n\t\t// note that this helper doesn't attempt to handle the callback\n\t\t// or setting of an html element's text, its only purpose is\n\t\t// to return the html encoded version of the text in all cases. (thus the name)\n\t\tgetEncodedText: function() {\n\t\t\treturn $( \"<a>\" ).text( this.text() ).html();\n\t\t},\n\n\t\t// fluent helper function for the mobile namespaced equivalent\n\t\tjqmEnhanceable: function() {\n\t\t\treturn $.mobile.enhanceable( this );\n\t\t},\n\n\t\tjqmHijackable: function() {\n\t\t\treturn $.mobile.hijackable( this );\n\t\t}\n\t});\n\n\t$.removeWithDependents = function( nativeElement ) {\n\t\tvar element = $( nativeElement );\n\n\t\t( element.jqmData( \"dependents\" ) || $() ).remove();\n\t\telement.remove();\n\t};\n\t$.addDependents = function( nativeElement, newDependents ) {\n\t\tvar element = $( nativeElement ),\n\t\t\tdependents = element.jqmData( \"dependents\" ) || $();\n\n\t\telement.jqmData( \"dependents\", $( dependents ).add( newDependents ) );\n\t};\n\n\t$.find.matches = function( expr, set ) {\n\t\treturn $.find( expr, null, null, set );\n\t};\n\n\t$.find.matchesSelector = function( node, expr ) {\n\t\treturn $.find( expr, null, null, [ node ] ).length > 0;\n\t};\n\n})( jQuery, this );\n\n(function( $, window, undefined ) {\n\t$.extend( $.mobile, {\n\n\t\t// Version of the jQuery Mobile Framework\n\t\tversion: \"1.4.5\",\n\n\t\t// Deprecated and no longer used in 1.4 remove in 1.5\n\t\t// Define the url parameter used for referencing widget-generated sub-pages.\n\t\t// Translates to example.html&ui-page=subpageIdentifier\n\t\t// hash segment before &ui-page= is used to make Ajax request\n\t\tsubPageUrlKey: \"ui-page\",\n\n\t\thideUrlBar: true,\n\n\t\t// Keepnative Selector\n\t\tkeepNative: \":jqmData(role='none'), :jqmData(role='nojs')\",\n\n\t\t// Deprecated in 1.4 remove in 1.5\n\t\t// Class assigned to page currently in view, and during transitions\n\t\tactivePageClass: \"ui-page-active\",\n\n\t\t// Deprecated in 1.4 remove in 1.5\n\t\t// Class used for \"active\" button state, from CSS framework\n\t\tactiveBtnClass: \"ui-btn-active\",\n\n\t\t// Deprecated in 1.4 remove in 1.5\n\t\t// Class used for \"focus\" form element state, from CSS framework\n\t\tfocusClass: \"ui-focus\",\n\n\t\t// Automatically handle clicks and form submissions through Ajax, when same-domain\n\t\tajaxEnabled: true,\n\n\t\t// Automatically load and show pages based on location.hash\n\t\thashListeningEnabled: true,\n\n\t\t// disable to prevent jquery from bothering with links\n\t\tlinkBindingEnabled: true,\n\n\t\t// Set default page transition - 'none' for no transitions\n\t\tdefaultPageTransition: \"fade\",\n\n\t\t// Set maximum window width for transitions to apply - 'false' for no limit\n\t\tmaxTransitionWidth: false,\n\n\t\t// Minimum scroll distance that will be remembered when returning to a page\n\t\t// Deprecated remove in 1.5\n\t\tminScrollBack: 0,\n\n\t\t// Set default dialog transition - 'none' for no transitions\n\t\tdefaultDialogTransition: \"pop\",\n\n\t\t// Error response message - appears when an Ajax page request fails\n\t\tpageLoadErrorMessage: \"Error Loading Page\",\n\n\t\t// For error messages, which theme does the box use?\n\t\tpageLoadErrorMessageTheme: \"a\",\n\n\t\t// replace calls to window.history.back with phonegaps navigation helper\n\t\t// where it is provided on the window object\n\t\tphonegapNavigationEnabled: false,\n\n\t\t//automatically initialize the DOM when it's ready\n\t\tautoInitializePage: true,\n\n\t\tpushStateEnabled: true,\n\n\t\t// allows users to opt in to ignoring content by marking a parent element as\n\t\t// data-ignored\n\t\tignoreContentEnabled: false,\n\n\t\tbuttonMarkup: {\n\t\t\thoverDelay: 200\n\t\t},\n\n\t\t// disable the alteration of the dynamic base tag or links in the case\n\t\t// that a dynamic base tag isn't supported\n\t\tdynamicBaseEnabled: true,\n\n\t\t// default the property to remove dependency on assignment in init module\n\t\tpageContainer: $(),\n\n\t\t//enable cross-domain page support\n\t\tallowCrossDomainPages: false,\n\n\t\tdialogHashKey: \"&ui-state=dialog\"\n\t});\n})( jQuery, this );\n\n/*!\n * jQuery UI Widget c0ab71056b936627e8a7821f03c044aec6280a40\n * http://jqueryui.com\n *\n * Copyright 2013 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/jQuery.widget/\n */\n(function( $, undefined ) {\n\nvar uuid = 0,\n\tslice = Array.prototype.slice,\n\t_cleanData = $.cleanData;\n$.cleanData = function( elems ) {\n\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n\t\ttry {\n\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t// http://bugs.jquery.com/ticket/8235\n\t\t} catch( e ) {}\n\t}\n\t_cleanData( elems );\n};\n\n$.widget = function( name, base, prototype ) {\n\tvar fullName, existingConstructor, constructor, basePrototype,\n\t\t// proxiedPrototype allows the provided prototype to remain unmodified\n\t\t// so that it can be used as a mixin for multiple widgets (#8876)\n\t\tproxiedPrototype = {},\n\t\tnamespace = name.split( \".\" )[ 0 ];\n\n\tname = name.split( \".\" )[ 1 ];\n\tfullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\t// create selector for plugin\n\t$.expr[ \":\" ][ fullName.toLowerCase() ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\t\t// allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\t// extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\t\t// copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\t\t// track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t});\n\n\tbasePrototype = new base();\n\t// we need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( !$.isFunction( value ) ) {\n\t\t\tproxiedPrototype[ prop ] = value;\n\t\t\treturn;\n\t\t}\n\t\tproxiedPrototype[ prop ] = (function() {\n\t\t\tvar _super = function() {\n\t\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t\t},\n\t\t\t\t_superApply = function( args ) {\n\t\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t\t};\n\t\t\treturn function() {\n\t\t\t\tvar __super = this._super,\n\t\t\t\t\t__superApply = this._superApply,\n\t\t\t\t\treturnValue;\n\n\t\t\t\tthis._super = _super;\n\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\tthis._super = __super;\n\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\treturn returnValue;\n\t\t\t};\n\t\t})();\n\t});\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name\n\t}, proxiedPrototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetFullName: fullName\n\t});\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor, child._proto );\n\t\t});\n\t\t// remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n\n\treturn constructor;\n};\n\n$.widget.extend = function( target ) {\n\tvar input = slice.call( arguments, 1 ),\n\t\tinputIndex = 0,\n\t\tinputLength = input.length,\n\t\tkey,\n\t\tvalue;\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\t\t\t\t// Clone objects\n\t\t\t\tif ( $.isPlainObject( value ) ) {\n\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n\t\t\t\t\t\t// Don't extend strings, arrays, etc. with objects\n\t\t\t\t\t\t$.widget.extend( {}, value );\n\t\t\t\t// Copy everything else by reference\n\t\t\t\t} else {\n\t\t\t\t\ttarget[ key ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName || name;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\",\n\t\t\targs = slice.call( arguments, 1 ),\n\t\t\treturnValue = this;\n\n\t\t// allow multiple hashes to be passed on init\n\t\toptions = !isMethodCall && args.length ?\n\t\t\t$.widget.extend.apply( null, [ options ].concat(args) ) :\n\t\t\toptions;\n\n\t\tif ( isMethodCall ) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar methodValue,\n\t\t\t\t\tinstance = $.data( this, fullName );\n\t\t\t\tif ( options === \"instance\" ) {\n\t\t\t\t\treturnValue = instance;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif ( !instance ) {\n\t\t\t\t\treturn $.error( \"cannot call methods on \" + name + \" prior to initialization; \" +\n\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t}\n\t\t\t\tif ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name + \" widget instance\" );\n\t\t\t\t}\n\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\tmethodValue;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.each(function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} )._init();\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( /* options, element */ ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\toptions: {\n\t\tdisabled: false,\n\n\t\t// callbacks\n\t\tcreate: null\n\t},\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.uuid = uuid++;\n\t\tthis.eventNamespace = \".\" + this.widgetName + this.uuid;\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\n\t\tif ( element !== this ) {\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._on( true, this.element, {\n\t\t\t\tremove: function( event ) {\n\t\t\t\t\tif ( event.target === element ) {\n\t\t\t\t\t\tthis.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis.document = $( element.style ?\n\t\t\t\t// element within the document\n\t\t\t\telement.ownerDocument :\n\t\t\t\t// element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[0].defaultView || this.document[0].parentWindow );\n\t\t}\n\n\t\tthis._create();\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\t_getCreateOptions: $.noop,\n\t_getCreateEventData: $.noop,\n\t_create: $.noop,\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tthis._destroy();\n\t\t// we can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._on()\n\t\tthis.element\n\t\t\t.unbind( this.eventNamespace )\n\t\t\t.removeData( this.widgetFullName )\n\t\t\t// support: jquery <1.6.3\n\t\t\t// http://bugs.jquery.com/ticket/9413\n\t\t\t.removeData( $.camelCase( this.widgetFullName ) );\n\t\tthis.widget()\n\t\t\t.unbind( this.eventNamespace )\n\t\t\t.removeAttr( \"aria-disabled\" )\n\t\t\t.removeClass(\n\t\t\t\tthis.widgetFullName + \"-disabled \" +\n\t\t\t\t\"ui-state-disabled\" );\n\n\t\t// clean up events and states\n\t\tthis.bindings.unbind( this.eventNamespace );\n\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t},\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key,\n\t\t\tparts,\n\t\t\tcurOption,\n\t\t\ti;\n\n\t\tif ( arguments.length === 0 ) {\n\t\t\t// don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\t\t\t// handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( value === undefined ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\t_setOption: function( key, value ) {\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis.widget()\n\t\t\t\t.toggleClass( this.widgetFullName + \"-disabled\", !!value );\n\t\t\tthis.hoverable.removeClass( \"ui-state-hover\" );\n\t\t\tthis.focusable.removeClass( \"ui-state-focus\" );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tenable: function() {\n\t\treturn this._setOptions({ disabled: false });\n\t},\n\tdisable: function() {\n\t\treturn this._setOptions({ disabled: true });\n\t},\n\n\t_on: function( suppressDisabledCheck, element, handlers ) {\n\t\tvar delegateElement,\n\t\t\tinstance = this;\n\n\t\t// no suppressDisabledCheck flag, shuffle arguments\n\t\tif ( typeof suppressDisabledCheck !== \"boolean\" ) {\n\t\t\thandlers = element;\n\t\t\telement = suppressDisabledCheck;\n\t\t\tsuppressDisabledCheck = false;\n\t\t}\n\n\t\t// no element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t\tdelegateElement = this.widget();\n\t\t} else {\n\t\t\t// accept selectors, DOM elements\n\t\t\telement = delegateElement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\t\t\t\t// allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( !suppressDisabledCheck &&\n\t\t\t\t\t\t( instance.options.disabled === true ||\n\t\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^(\\w+)\\s*(.*)$/ ),\n\t\t\t\teventName = match[1] + instance.eventNamespace,\n\t\t\t\tselector = match[2];\n\t\t\tif ( selector ) {\n\t\t\t\tdelegateElement.delegate( selector, eventName, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.bind( eventName, handlerProxy );\n\t\t\t}\n\t\t});\n\t},\n\n\t_off: function( element, eventName ) {\n\t\teventName = (eventName || \"\").split( \" \" ).join( this.eventNamespace + \" \" ) + this.eventNamespace;\n\t\telement.unbind( eventName ).undelegate( eventName );\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._on( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-hover\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._on( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\t$( event.currentTarget ).addClass( \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\t$( event.currentTarget ).removeClass( \"ui-state-focus\" );\n\t\t\t}\n\t\t});\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig,\n\t\t\tcallback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\t\t// the original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[0], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\t\tvar hasOptions,\n\t\t\teffectName = !options ?\n\t\t\t\tmethod :\n\t\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\t\tdefaultEffect :\n\t\t\t\t\toptions.effect || defaultEffect;\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue(function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t});\n\t\t}\n\t};\n});\n\n})( jQuery );\n\n(function( $, window, undefined ) {\n\tvar nsNormalizeDict = {},\n\t\toldFind = $.find,\n\t\trbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\t\tjqmDataRE = /:jqmData\\(([^)]*)\\)/g;\n\n\t$.extend( $.mobile, {\n\n\t\t// Namespace used framework-wide for data-attrs. Default is no namespace\n\n\t\tns: \"\",\n\n\t\t// Retrieve an attribute from an element and perform some massaging of the value\n\n\t\tgetAttribute: function( element, key ) {\n\t\t\tvar data;\n\n\t\t\telement = element.jquery ? element[0] : element;\n\n\t\t\tif ( element && element.getAttribute ) {\n\t\t\t\tdata = element.getAttribute( \"data-\" + $.mobile.ns + key );\n\t\t\t}\n\n\t\t\t// Copied from core's src/data.js:dataAttr()\n\t\t\t// Convert from a string to a proper data type\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? JSON.parse( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( err ) {}\n\n\t\t\treturn data;\n\t\t},\n\n\t\t// Expose our cache for testing purposes.\n\t\tnsNormalizeDict: nsNormalizeDict,\n\n\t\t// Take a data attribute property, prepend the namespace\n\t\t// and then camel case the attribute string. Add the result\n\t\t// to our nsNormalizeDict so we don't have to do this again.\n\t\tnsNormalize: function( prop ) {\n\t\t\treturn nsNormalizeDict[ prop ] ||\n\t\t\t\t( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) );\n\t\t},\n\n\t\t// Find the closest javascript page element to gather settings data jsperf test\n\t\t// http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit\n\t\t// possibly naive, but it shows that the parsing overhead for *just* the page selector vs\n\t\t// the page and dialog selector is negligable. This could probably be speed up by\n\t\t// doing a similar parent node traversal to the one found in the inherited theme code above\n\t\tclosestPageData: function( $target ) {\n\t\t\treturn $target\n\t\t\t\t.closest( \":jqmData(role='page'), :jqmData(role='dialog')\" )\n\t\t\t\t.data( \"mobile-page\" );\n\t\t}\n\n\t});\n\n\t// Mobile version of data and removeData and hasData methods\n\t// ensures all data is set and retrieved using jQuery Mobile's data namespace\n\t$.fn.jqmData = function( prop, value ) {\n\t\tvar result;\n\t\tif ( typeof prop !== \"undefined\" ) {\n\t\t\tif ( prop ) {\n\t\t\t\tprop = $.mobile.nsNormalize( prop );\n\t\t\t}\n\n\t\t\t// undefined is permitted as an explicit input for the second param\n\t\t\t// in this case it returns the value and does not set it to undefined\n\t\t\tif ( arguments.length < 2 || value === undefined ) {\n\t\t\t\tresult = this.data( prop );\n\t\t\t} else {\n\t\t\t\tresult = this.data( prop, value );\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t};\n\n\t$.jqmData = function( elem, prop, value ) {\n\t\tvar result;\n\t\tif ( typeof prop !== \"undefined\" ) {\n\t\t\tresult = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );\n\t\t}\n\t\treturn result;\n\t};\n\n\t$.fn.jqmRemoveData = function( prop ) {\n\t\treturn this.removeData( $.mobile.nsNormalize( prop ) );\n\t};\n\n\t$.jqmRemoveData = function( elem, prop ) {\n\t\treturn $.removeData( elem, $.mobile.nsNormalize( prop ) );\n\t};\n\n\t$.find = function( selector, context, ret, extra ) {\n\t\tif ( selector.indexOf( \":jqmData\" ) > -1 ) {\n\t\t\tselector = selector.replace( jqmDataRE, \"[data-\" + ( $.mobile.ns || \"\" ) + \"$1]\" );\n\t\t}\n\n\t\treturn oldFind.call( this, selector, context, ret, extra );\n\t};\n\n\t$.extend( $.find, oldFind );\n\n})( jQuery, this );\n\n(function( $, undefined ) {\n\nvar rcapitals = /[A-Z]/g,\n\treplaceFunction = function( c ) {\n\t\treturn \"-\" + c.toLowerCase();\n\t};\n\n$.extend( $.Widget.prototype, {\n\t_getCreateOptions: function() {\n\t\tvar option, value,\n\t\t\telem = this.element[ 0 ],\n\t\t\toptions = {};\n\n\t\t//\n\t\tif ( !$.mobile.getAttribute( elem, \"defaults\" ) ) {\n\t\t\tfor ( option in this.options ) {\n\t\t\t\tvalue = $.mobile.getAttribute( elem, option.replace( rcapitals, replaceFunction ) );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\toptions[ option ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn options;\n\t}\n});\n\n//TODO: Remove in 1.5 for backcompat only\n$.mobile.widget = $.Widget;\n\n})( jQuery );\n\n\n(function( $ ) {\n\t// TODO move loader class down into the widget settings\n\tvar loaderClass = \"ui-loader\", $html = $( \"html\" );\n\n\t$.widget( \"mobile.loader\", {\n\t\t// NOTE if the global config settings are defined they will override these\n\t\t//      options\n\t\toptions: {\n\t\t\t// the theme for the loading message\n\t\t\ttheme: \"a\",\n\n\t\t\t// whether the text in the loading message is shown\n\t\t\ttextVisible: false,\n\n\t\t\t// custom html for the inner content of the loading message\n\t\t\thtml: \"\",\n\n\t\t\t// the text to be displayed when the popup is shown\n\t\t\ttext: \"loading\"\n\t\t},\n\n\t\tdefaultHtml: \"<div class='\" + loaderClass + \"'>\" +\n\t\t\t\"<span class='ui-icon-loading'></span>\" +\n\t\t\t\"<h1></h1>\" +\n\t\t\t\"</div>\",\n\n\t\t// For non-fixed supportin browsers. Position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top\n\t\tfakeFixLoader: function() {\n\t\t\tvar activeBtn = $( \".\" + $.mobile.activeBtnClass ).first();\n\n\t\t\tthis.element\n\t\t\t\t.css({\n\t\t\t\t\ttop: $.support.scrollTop && this.window.scrollTop() + this.window.height() / 2 ||\n\t\t\t\t\t\tactiveBtn.length && activeBtn.offset().top || 100\n\t\t\t\t});\n\t\t},\n\n\t\t// check position of loader to see if it appears to be \"fixed\" to center\n\t\t// if not, use abs positioning\n\t\tcheckLoaderPosition: function() {\n\t\t\tvar offset = this.element.offset(),\n\t\t\t\tscrollTop = this.window.scrollTop(),\n\t\t\t\tscreenHeight = $.mobile.getScreenHeight();\n\n\t\t\tif ( offset.top < scrollTop || ( offset.top - scrollTop ) > screenHeight ) {\n\t\t\t\tthis.element.addClass( \"ui-loader-fakefix\" );\n\t\t\t\tthis.fakeFixLoader();\n\t\t\t\tthis.window\n\t\t\t\t\t.unbind( \"scroll\", this.checkLoaderPosition )\n\t\t\t\t\t.bind( \"scroll\", $.proxy( this.fakeFixLoader, this ) );\n\t\t\t}\n\t\t},\n\n\t\tresetHtml: function() {\n\t\t\tthis.element.html( $( this.defaultHtml ).html() );\n\t\t},\n\n\t\t// Turn on/off page loading message. Theme doubles as an object argument\n\t\t// with the following shape: { theme: '', text: '', html: '', textVisible: '' }\n\t\t// NOTE that the $.mobile.loading* settings and params past the first are deprecated\n\t\t// TODO sweet jesus we need to break some of this out\n\t\tshow: function( theme, msgText, textonly ) {\n\t\t\tvar textVisible, message, loadSettings;\n\n\t\t\tthis.resetHtml();\n\n\t\t\t// use the prototype options so that people can set them globally at\n\t\t\t// mobile init. Consistency, it's what's for dinner\n\t\t\tif ( $.type( theme ) === \"object\" ) {\n\t\t\t\tloadSettings = $.extend( {}, this.options, theme );\n\n\t\t\t\ttheme = loadSettings.theme;\n\t\t\t} else {\n\t\t\t\tloadSettings = this.options;\n\n\t\t\t\t// here we prefer the theme value passed as a string argument, then\n\t\t\t\t// we prefer the global option because we can't use undefined default\n\t\t\t\t// prototype options, then the prototype option\n\t\t\t\ttheme = theme || loadSettings.theme;\n\t\t\t}\n\n\t\t\t// set the message text, prefer the param, then the settings object\n\t\t\t// then loading message\n\t\t\tmessage = msgText || ( loadSettings.text === false ? \"\" : loadSettings.text );\n\n\t\t\t// prepare the dom\n\t\t\t$html.addClass( \"ui-loading\" );\n\n\t\t\ttextVisible = loadSettings.textVisible;\n\n\t\t\t// add the proper css given the options (theme, text, etc)\n\t\t\t// Force text visibility if the second argument was supplied, or\n\t\t\t// if the text was explicitly set in the object args\n\t\t\tthis.element.attr(\"class\", loaderClass +\n\t\t\t\t\" ui-corner-all ui-body-\" + theme +\n\t\t\t\t\" ui-loader-\" + ( textVisible || msgText || theme.text ? \"verbose\" : \"default\" ) +\n\t\t\t\t( loadSettings.textonly || textonly ? \" ui-loader-textonly\" : \"\" ) );\n\n\t\t\t// TODO verify that jquery.fn.html is ok to use in both cases here\n\t\t\t//      this might be overly defensive in preventing unknowing xss\n\t\t\t// if the html attribute is defined on the loading settings, use that\n\t\t\t// otherwise use the fallbacks from above\n\t\t\tif ( loadSettings.html ) {\n\t\t\t\tthis.element.html( loadSettings.html );\n\t\t\t} else {\n\t\t\t\tthis.element.find( \"h1\" ).text( message );\n\t\t\t}\n\n\t\t\t// If the pagecontainer widget has been defined we may use the :mobile-pagecontainer\n\t\t\t// and attach to the element on which the pagecontainer widget has been defined. If not,\n\t\t\t// we attach to the body.\n\t\t\tthis.element.appendTo( $.mobile.pagecontainer ?\n\t\t\t\t$( \":mobile-pagecontainer\" ) : $( \"body\" ) );\n\n\t\t\t// check that the loader is visible\n\t\t\tthis.checkLoaderPosition();\n\n\t\t\t// on scroll check the loader position\n\t\t\tthis.window.bind( \"scroll\", $.proxy( this.checkLoaderPosition, this ) );\n\t\t},\n\n\t\thide: function() {\n\t\t\t$html.removeClass( \"ui-loading\" );\n\n\t\t\tif ( this.options.text ) {\n\t\t\t\tthis.element.removeClass( \"ui-loader-fakefix\" );\n\t\t\t}\n\n\t\t\tthis.window.unbind( \"scroll\", this.fakeFixLoader );\n\t\t\tthis.window.unbind( \"scroll\", this.checkLoaderPosition );\n\t\t}\n\t});\n\n})(jQuery, this);\n\n\n/*!\n * jQuery hashchange event - v1.3 - 7/21/2010\n * http://benalman.com/projects/jquery-hashchange-plugin/\n * \n * Copyright (c) 2010 \"Cowboy\" Ben Alman\n * Dual licensed under the MIT and GPL licenses.\n * http://benalman.com/about/license/\n */\n\n// Script: jQuery hashchange event\n//\n// *Version: 1.3, Last updated: 7/21/2010*\n// \n// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/\n// GitHub       - http://github.com/cowboy/jquery-hashchange/\n// Source       - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js\n// (Minified)   - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)\n// \n// About: License\n// \n// Copyright (c) 2010 \"Cowboy\" Ben Alman,\n// Dual licensed under the MIT and GPL licenses.\n// http://benalman.com/about/license/\n// \n// About: Examples\n// \n// These working examples, complete with fully commented code, illustrate a few\n// ways in which this plugin can be used.\n// \n// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/\n// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/\n// \n// About: Support and Testing\n// \n// Information about what version or versions of jQuery this plugin has been\n// tested with, what browsers it has been tested in, and where the unit tests\n// reside (so you can test it yourself).\n// \n// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2\n// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,\n//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.\n// Unit Tests      - http://benalman.com/code/projects/jquery-hashchange/unit/\n// \n// About: Known issues\n// \n// While this jQuery hashchange event implementation is quite stable and\n// robust, there are a few unfortunate browser bugs surrounding expected\n// hashchange event-based behaviors, independent of any JavaScript\n// window.onhashchange abstraction. See the following examples for more\n// information:\n// \n// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/\n// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/\n// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/\n// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/\n// \n// Also note that should a browser natively support the window.onhashchange \n// event, but not report that it does, the fallback polling loop will be used.\n// \n// About: Release History\n// \n// 1.3   - (7/21/2010) Reorganized IE6/7 Iframe code to make it more\n//         \"removable\" for mobile-only development. Added IE6/7 document.title\n//         support. Attempted to make Iframe as hidden as possible by using\n//         techniques from http://www.paciellogroup.com/blog/?p=604. Added \n//         support for the \"shortcut\" format $(window).hashchange( fn ) and\n//         $(window).hashchange() like jQuery provides for built-in events.\n//         Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and\n//         lowered its default value to 50. Added <jQuery.fn.hashchange.domain>\n//         and <jQuery.fn.hashchange.src> properties plus document-domain.html\n//         file to address access denied issues when setting document.domain in\n//         IE6/7.\n// 1.2   - (2/11/2010) Fixed a bug where coming back to a page using this plugin\n//         from a page on another domain would cause an error in Safari 4. Also,\n//         IE6/7 Iframe is now inserted after the body (this actually works),\n//         which prevents the page from scrolling when the event is first bound.\n//         Event can also now be bound before DOM ready, but it won't be usable\n//         before then in IE6/7.\n// 1.1   - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug\n//         where browser version is incorrectly reported as 8.0, despite\n//         inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.\n// 1.0   - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special\n//         window.onhashchange functionality into a separate plugin for users\n//         who want just the basic event & back button support, without all the\n//         extra awesomeness that BBQ provides. This plugin will be included as\n//         part of jQuery BBQ, but also be available separately.\n\n(function($,window,undefined){\n  '$:nomunge'; // Used by YUI compressor.\n  \n  // Reused string.\n  var str_hashchange = 'hashchange',\n    \n    // Method / object references.\n    doc = document,\n    fake_onhashchange,\n    special = $.event.special,\n    \n    // Does the browser support window.onhashchange? Note that IE8 running in\n    // IE7 compatibility mode reports true for 'onhashchange' in window, even\n    // though the event isn't supported, so also test document.documentMode.\n    doc_mode = doc.documentMode,\n    supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );\n  \n  // Get location.hash (or what you'd expect location.hash to be) sans any\n  // leading #. Thanks for making this necessary, Firefox!\n  function get_fragment( url ) {\n    url = url || location.href;\n    return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );\n  };\n  \n  // Method: jQuery.fn.hashchange\n  // \n  // Bind a handler to the window.onhashchange event or trigger all bound\n  // window.onhashchange event handlers. This behavior is consistent with\n  // jQuery's built-in event handlers.\n  // \n  // Usage:\n  // \n  // > jQuery(window).hashchange( [ handler ] );\n  // \n  // Arguments:\n  // \n  //  handler - (Function) Optional handler to be bound to the hashchange\n  //    event. This is a \"shortcut\" for the more verbose form:\n  //    jQuery(window).bind( 'hashchange', handler ). If handler is omitted,\n  //    all bound window.onhashchange event handlers will be triggered. This\n  //    is a shortcut for the more verbose\n  //    jQuery(window).trigger( 'hashchange' ). These forms are described in\n  //    the <hashchange event> section.\n  // \n  // Returns:\n  // \n  //  (jQuery) The initial jQuery collection of elements.\n  \n  // Allow the \"shortcut\" format $(elem).hashchange( fn ) for binding and\n  // $(elem).hashchange() for triggering, like jQuery does for built-in events.\n  $.fn[ str_hashchange ] = function( fn ) {\n    return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );\n  };\n  \n  // Property: jQuery.fn.hashchange.delay\n  // \n  // The numeric interval (in milliseconds) at which the <hashchange event>\n  // polling loop executes. Defaults to 50.\n  \n  // Property: jQuery.fn.hashchange.domain\n  // \n  // If you're setting document.domain in your JavaScript, and you want hash\n  // history to work in IE6/7, not only must this property be set, but you must\n  // also set document.domain BEFORE jQuery is loaded into the page. This\n  // property is only applicable if you are supporting IE6/7 (or IE8 operating\n  // in \"IE7 compatibility\" mode).\n  // \n  // In addition, the <jQuery.fn.hashchange.src> property must be set to the\n  // path of the included \"document-domain.html\" file, which can be renamed or\n  // modified if necessary (note that the document.domain specified must be the\n  // same in both your main JavaScript as well as in this file).\n  // \n  // Usage:\n  // \n  // jQuery.fn.hashchange.domain = document.domain;\n  \n  // Property: jQuery.fn.hashchange.src\n  // \n  // If, for some reason, you need to specify an Iframe src file (for example,\n  // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can\n  // do so using this property. Note that when using this property, history\n  // won't be recorded in IE6/7 until the Iframe src file loads. This property\n  // is only applicable if you are supporting IE6/7 (or IE8 operating in \"IE7\n  // compatibility\" mode).\n  // \n  // Usage:\n  // \n  // jQuery.fn.hashchange.src = 'path/to/file.html';\n  \n  $.fn[ str_hashchange ].delay = 50;\n  /*\n  $.fn[ str_hashchange ].domain = null;\n  $.fn[ str_hashchange ].src = null;\n  */\n  \n  // Event: hashchange event\n  // \n  // Fired when location.hash changes. In browsers that support it, the native\n  // HTML5 window.onhashchange event is used, otherwise a polling loop is\n  // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to\n  // see if the hash has changed. In IE6/7 (and IE8 operating in \"IE7\n  // compatibility\" mode), a hidden Iframe is created to allow the back button\n  // and hash-based history to work.\n  // \n  // Usage as described in <jQuery.fn.hashchange>:\n  // \n  // > // Bind an event handler.\n  // > jQuery(window).hashchange( function(e) {\n  // >   var hash = location.hash;\n  // >   ...\n  // > });\n  // > \n  // > // Manually trigger the event handler.\n  // > jQuery(window).hashchange();\n  // \n  // A more verbose usage that allows for event namespacing:\n  // \n  // > // Bind an event handler.\n  // > jQuery(window).bind( 'hashchange', function(e) {\n  // >   var hash = location.hash;\n  // >   ...\n  // > });\n  // > \n  // > // Manually trigger the event handler.\n  // > jQuery(window).trigger( 'hashchange' );\n  // \n  // Additional Notes:\n  // \n  // * The polling loop and Iframe are not created until at least one handler\n  //   is actually bound to the 'hashchange' event.\n  // * If you need the bound handler(s) to execute immediately, in cases where\n  //   a location.hash exists on page load, via bookmark or page refresh for\n  //   example, use jQuery(window).hashchange() or the more verbose \n  //   jQuery(window).trigger( 'hashchange' ).\n  // * The event can be bound before DOM ready, but since it won't be usable\n  //   before then in IE6/7 (due to the necessary Iframe), recommended usage is\n  //   to bind it inside a DOM ready handler.\n  \n  // Override existing $.event.special.hashchange methods (allowing this plugin\n  // to be defined after jQuery BBQ in BBQ's source code).\n  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {\n    \n    // Called only when the first 'hashchange' event is bound to window.\n    setup: function() {\n      // If window.onhashchange is supported natively, there's nothing to do..\n      if ( supports_onhashchange ) { return false; }\n      \n      // Otherwise, we need to create our own. And we don't want to call this\n      // until the user binds to the event, just in case they never do, since it\n      // will create a polling loop and possibly even a hidden Iframe.\n      $( fake_onhashchange.start );\n    },\n    \n    // Called only when the last 'hashchange' event is unbound from window.\n    teardown: function() {\n      // If window.onhashchange is supported natively, there's nothing to do..\n      if ( supports_onhashchange ) { return false; }\n      \n      // Otherwise, we need to stop ours (if possible).\n      $( fake_onhashchange.stop );\n    }\n    \n  });\n  \n  // fake_onhashchange does all the work of triggering the window.onhashchange\n  // event for browsers that don't natively support it, including creating a\n  // polling loop to watch for hash changes and in IE 6/7 creating a hidden\n  // Iframe to enable back and forward.\n  fake_onhashchange = (function(){\n    var self = {},\n      timeout_id,\n      \n      // Remember the initial hash so it doesn't get triggered immediately.\n      last_hash = get_fragment(),\n      \n      fn_retval = function(val){ return val; },\n      history_set = fn_retval,\n      history_get = fn_retval;\n    \n    // Start the polling loop.\n    self.start = function() {\n      timeout_id || poll();\n    };\n    \n    // Stop the polling loop.\n    self.stop = function() {\n      timeout_id && clearTimeout( timeout_id );\n      timeout_id = undefined;\n    };\n    \n    // This polling loop checks every $.fn.hashchange.delay milliseconds to see\n    // if location.hash has changed, and triggers the 'hashchange' event on\n    // window when necessary.\n    function poll() {\n      var hash = get_fragment(),\n        history_hash = history_get( last_hash );\n      \n      if ( hash !== last_hash ) {\n        history_set( last_hash = hash, history_hash );\n        \n        $(window).trigger( str_hashchange );\n        \n      } else if ( history_hash !== last_hash ) {\n        location.href = location.href.replace( /#.*/, '' ) + history_hash;\n      }\n      \n      timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );\n    };\n    \n    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n    // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv\n    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n    window.attachEvent && !window.addEventListener && !supports_onhashchange && (function(){\n      // Not only do IE6/7 need the \"magical\" Iframe treatment, but so does IE8\n      // when running in \"IE7 compatibility\" mode.\n      \n      var iframe,\n        iframe_src;\n      \n      // When the event is bound and polling starts in IE 6/7, create a hidden\n      // Iframe for history handling.\n      self.start = function(){\n        if ( !iframe ) {\n          iframe_src = $.fn[ str_hashchange ].src;\n          iframe_src = iframe_src && iframe_src + get_fragment();\n          \n          // Create hidden Iframe. Attempt to make Iframe as hidden as possible\n          // by using techniques from http://www.paciellogroup.com/blog/?p=604.\n          iframe = $('<iframe tabindex=\"-1\" title=\"empty\"/>').hide()\n            \n            // When Iframe has completely loaded, initialize the history and\n            // start polling.\n            .one( 'load', function(){\n              iframe_src || history_set( get_fragment() );\n              poll();\n            })\n            \n            // Load Iframe src if specified, otherwise nothing.\n            .attr( 'src', iframe_src || 'javascript:0' )\n            \n            // Append Iframe after the end of the body to prevent unnecessary\n            // initial page scrolling (yes, this works).\n            .insertAfter( 'body' )[0].contentWindow;\n          \n          // Whenever `document.title` changes, update the Iframe's title to\n          // prettify the back/next history menu entries. Since IE sometimes\n          // errors with \"Unspecified error\" the very first time this is set\n          // (yes, very useful) wrap this with a try/catch block.\n          doc.onpropertychange = function(){\n            try {\n              if ( event.propertyName === 'title' ) {\n                iframe.document.title = doc.title;\n              }\n            } catch(e) {}\n          };\n          \n        }\n      };\n      \n      // Override the \"stop\" method since an IE6/7 Iframe was created. Even\n      // if there are no longer any bound event handlers, the polling loop\n      // is still necessary for back/next to work at all!\n      self.stop = fn_retval;\n      \n      // Get history by looking at the hidden Iframe's location.hash.\n      history_get = function() {\n        return get_fragment( iframe.location.href );\n      };\n      \n      // Set a new history item by opening and then closing the Iframe\n      // document, *then* setting its location.hash. If document.domain has\n      // been set, update that as well.\n      history_set = function( hash, history_hash ) {\n        var iframe_doc = iframe.document,\n          domain = $.fn[ str_hashchange ].domain;\n        \n        if ( hash !== history_hash ) {\n          // Update Iframe with any initial `document.title` that might be set.\n          iframe_doc.title = doc.title;\n          \n          // Opening the Iframe's document after it has been closed is what\n          // actually adds a history entry.\n          iframe_doc.open();\n          \n          // Set document.domain for the Iframe document as well, if necessary.\n          domain && iframe_doc.write( '\\x3cscript>document.domain=\"' + domain + '\"\\x3c/script>' );\n          \n          iframe_doc.close();\n          \n          // Update the Iframe's hash, for great justice.\n          iframe.location.hash = hash;\n        }\n      };\n      \n    })();\n    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^\n    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    \n    return self;\n  })();\n  \n})(jQuery,this);\n\n\n(function( $, undefined ) {\n\n\t/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */\n\twindow.matchMedia = window.matchMedia || (function( doc, undefined ) {\n\n\t\tvar bool,\n\t\t\tdocElem = doc.documentElement,\n\t\t\trefNode = docElem.firstElementChild || docElem.firstChild,\n\t\t\t// fakeBody required for <FF4 when executed in <head>\n\t\t\tfakeBody = doc.createElement( \"body\" ),\n\t\t\tdiv = doc.createElement( \"div\" );\n\n\t\tdiv.id = \"mq-test-1\";\n\t\tdiv.style.cssText = \"position:absolute;top:-100em\";\n\t\tfakeBody.style.background = \"none\";\n\t\tfakeBody.appendChild(div);\n\n\t\treturn function(q){\n\n\t\t\tdiv.innerHTML = \"&shy;<style media=\\\"\" + q + \"\\\"> #mq-test-1 { width: 42px; }</style>\";\n\n\t\t\tdocElem.insertBefore( fakeBody, refNode );\n\t\t\tbool = div.offsetWidth === 42;\n\t\t\tdocElem.removeChild( fakeBody );\n\n\t\t\treturn {\n\t\t\t\tmatches: bool,\n\t\t\t\tmedia: q\n\t\t\t};\n\n\t\t};\n\n\t}( document ));\n\n\t// $.mobile.media uses matchMedia to return a boolean.\n\t$.mobile.media = function( q ) {\n\t\treturn window.matchMedia( q ).matches;\n\t};\n\n})(jQuery);\n\n\t(function( $, undefined ) {\n\t\tvar support = {\n\t\t\ttouch: \"ontouchend\" in document\n\t\t};\n\n\t\t$.mobile.support = $.mobile.support || {};\n\t\t$.extend( $.support, support );\n\t\t$.extend( $.mobile.support, support );\n\t}( jQuery ));\n\n\t(function( $, undefined ) {\n\t\t$.extend( $.support, {\n\t\t\torientation: \"orientation\" in window && \"onorientationchange\" in window\n\t\t});\n\t}( jQuery ));\n\n(function( $, undefined ) {\n\n// thx Modernizr\nfunction propExists( prop ) {\n\tvar uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),\n\t\tprops = ( prop + \" \" + vendors.join( uc_prop + \" \" ) + uc_prop ).split( \" \" ),\n\t\tv;\n\n\tfor ( v in props ) {\n\t\tif ( fbCSS[ props[ v ] ] !== undefined ) {\n\t\t\treturn true;\n\t\t}\n\t}\n}\n\nvar fakeBody = $( \"<body>\" ).prependTo( \"html\" ),\n\tfbCSS = fakeBody[ 0 ].style,\n\tvendors = [ \"Webkit\", \"Moz\", \"O\" ],\n\twebos = \"palmGetResource\" in window, //only used to rule out scrollTop\n\toperamini = window.operamini && ({}).toString.call( window.operamini ) === \"[object OperaMini]\",\n\tbb = window.blackberry && !propExists( \"-webkit-transform\" ), //only used to rule out box shadow, as it's filled opaque on BB 5 and lower\n\tnokiaLTE7_3;\n\n// inline SVG support test\nfunction inlineSVG() {\n\t// Thanks Modernizr & Erik Dahlstrom\n\tvar w = window,\n\t\tsvg = !!w.document.createElementNS && !!w.document.createElementNS( \"http://www.w3.org/2000/svg\", \"svg\" ).createSVGRect && !( w.opera && navigator.userAgent.indexOf( \"Chrome\" ) === -1 ),\n\t\tsupport = function( data ) {\n\t\t\tif ( !( data && svg ) ) {\n\t\t\t\t$( \"html\" ).addClass( \"ui-nosvg\" );\n\t\t\t}\n\t\t},\n\t\timg = new w.Image();\n\n\timg.onerror = function() {\n\t\tsupport( false );\n\t};\n\timg.onload = function() {\n\t\tsupport( img.width === 1 && img.height === 1 );\n\t};\n\timg.src = \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\";\n}\n\nfunction transform3dTest() {\n\tvar mqProp = \"transform-3d\",\n\t\t// Because the `translate3d` test below throws false positives in Android:\n\t\tret = $.mobile.media( \"(-\" + vendors.join( \"-\" + mqProp + \"),(-\" ) + \"-\" + mqProp + \"),(\" + mqProp + \")\" ),\n\t\tel, transforms, t;\n\n\tif ( ret ) {\n\t\treturn !!ret;\n\t}\n\n\tel = document.createElement( \"div\" );\n\ttransforms = {\n\t\t// We’re omitting Opera for the time being; MS uses unprefixed.\n\t\t\"MozTransform\": \"-moz-transform\",\n\t\t\"transform\": \"transform\"\n\t};\n\n\tfakeBody.append( el );\n\n\tfor ( t in transforms ) {\n\t\tif ( el.style[ t ] !== undefined ) {\n\t\t\tel.style[ t ] = \"translate3d( 100px, 1px, 1px )\";\n\t\t\tret = window.getComputedStyle( el ).getPropertyValue( transforms[ t ] );\n\t\t}\n\t}\n\treturn ( !!ret && ret !== \"none\" );\n}\n\n// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting )\nfunction baseTagTest() {\n\tvar fauxBase = location.protocol + \"//\" + location.host + location.pathname + \"ui-dir/\",\n\t\tbase = $( \"head base\" ),\n\t\tfauxEle = null,\n\t\thref = \"\",\n\t\tlink, rebase;\n\n\tif ( !base.length ) {\n\t\tbase = fauxEle = $( \"<base>\", { \"href\": fauxBase }).appendTo( \"head\" );\n\t} else {\n\t\thref = base.attr( \"href\" );\n\t}\n\n\tlink = $( \"<a href='testurl' />\" ).prependTo( fakeBody );\n\trebase = link[ 0 ].href;\n\tbase[ 0 ].href = href || location.pathname;\n\n\tif ( fauxEle ) {\n\t\tfauxEle.remove();\n\t}\n\treturn rebase.indexOf( fauxBase ) === 0;\n}\n\n// Thanks Modernizr\nfunction cssPointerEventsTest() {\n\tvar element = document.createElement( \"x\" ),\n\t\tdocumentElement = document.documentElement,\n\t\tgetComputedStyle = window.getComputedStyle,\n\t\tsupports;\n\n\tif ( !( \"pointerEvents\" in element.style ) ) {\n\t\treturn false;\n\t}\n\n\telement.style.pointerEvents = \"auto\";\n\telement.style.pointerEvents = \"x\";\n\tdocumentElement.appendChild( element );\n\tsupports = getComputedStyle &&\n\tgetComputedStyle( element, \"\" ).pointerEvents === \"auto\";\n\tdocumentElement.removeChild( element );\n\treturn !!supports;\n}\n\nfunction boundingRect() {\n\tvar div = document.createElement( \"div\" );\n\treturn typeof div.getBoundingClientRect !== \"undefined\";\n}\n\n// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683\n// allows for inclusion of IE 6+, including Windows Mobile 7\n$.extend( $.mobile, { browser: {} } );\n$.mobile.browser.oldIE = (function() {\n\tvar v = 3,\n\t\tdiv = document.createElement( \"div\" ),\n\t\ta = div.all || [];\n\n\tdo {\n\t\tdiv.innerHTML = \"<!--[if gt IE \" + ( ++v ) + \"]><br><![endif]-->\";\n\t} while( a[0] );\n\n\treturn v > 4 ? v : !v;\n})();\n\nfunction fixedPosition() {\n\tvar w = window,\n\t\tua = navigator.userAgent,\n\t\tplatform = navigator.platform,\n\t\t// Rendering engine is Webkit, and capture major version\n\t\twkmatch = ua.match( /AppleWebKit\\/([0-9]+)/ ),\n\t\twkversion = !!wkmatch && wkmatch[ 1 ],\n\t\tffmatch = ua.match( /Fennec\\/([0-9]+)/ ),\n\t\tffversion = !!ffmatch && ffmatch[ 1 ],\n\t\toperammobilematch = ua.match( /Opera Mobi\\/([0-9]+)/ ),\n\t\tomversion = !!operammobilematch && operammobilematch[ 1 ];\n\n\tif (\n\t\t// iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)\n\t\t( ( platform.indexOf( \"iPhone\" ) > -1 || platform.indexOf( \"iPad\" ) > -1  || platform.indexOf( \"iPod\" ) > -1 ) && wkversion && wkversion < 534 ) ||\n\t\t// Opera Mini\n\t\t( w.operamini && ({}).toString.call( w.operamini ) === \"[object OperaMini]\" ) ||\n\t\t( operammobilematch && omversion < 7458 )\t||\n\t\t//Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)\n\t\t( ua.indexOf( \"Android\" ) > -1 && wkversion && wkversion < 533 ) ||\n\t\t// Firefox Mobile before 6.0 -\n\t\t( ffversion && ffversion < 6 ) ||\n\t\t// WebOS less than 3\n\t\t( \"palmGetResource\" in window && wkversion && wkversion < 534 )\t||\n\t\t// MeeGo\n\t\t( ua.indexOf( \"MeeGo\" ) > -1 && ua.indexOf( \"NokiaBrowser/8.5.0\" ) > -1 ) ) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n$.extend( $.support, {\n\t// Note, Chrome for iOS has an extremely quirky implementation of popstate.\n\t// We've chosen to take the shortest path to a bug fix here for issue #5426\n\t// See the following link for information about the regex chosen\n\t// https://developers.google.com/chrome/mobile/docs/user-agent#chrome_for_ios_user-agent\n\tpushState: \"pushState\" in history &&\n\t\t\"replaceState\" in history &&\n\t\t// When running inside a FF iframe, calling replaceState causes an error\n\t\t!( window.navigator.userAgent.indexOf( \"Firefox\" ) >= 0 && window.top !== window ) &&\n\t\t( window.navigator.userAgent.search(/CriOS/) === -1 ),\n\n\tmediaquery: $.mobile.media( \"only all\" ),\n\tcssPseudoElement: !!propExists( \"content\" ),\n\ttouchOverflow: !!propExists( \"overflowScrolling\" ),\n\tcssTransform3d: transform3dTest(),\n\tboxShadow: !!propExists( \"boxShadow\" ) && !bb,\n\tfixedPosition: fixedPosition(),\n\tscrollTop: (\"pageXOffset\" in window ||\n\t\t\"scrollTop\" in document.documentElement ||\n\t\t\"scrollTop\" in fakeBody[ 0 ]) && !webos && !operamini,\n\n\tdynamicBaseTag: baseTagTest(),\n\tcssPointerEvents: cssPointerEventsTest(),\n\tboundingRect: boundingRect(),\n\tinlineSVG: inlineSVG\n});\n\nfakeBody.remove();\n\n// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian)\n// or that generally work better browsing in regular http for full page refreshes (Opera Mini)\n// Note: This detection below is used as a last resort.\n// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible\nnokiaLTE7_3 = (function() {\n\n\tvar ua = window.navigator.userAgent;\n\n\t//The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older\n\treturn ua.indexOf( \"Nokia\" ) > -1 &&\n\t\t\t( ua.indexOf( \"Symbian/3\" ) > -1 || ua.indexOf( \"Series60/5\" ) > -1 ) &&\n\t\t\tua.indexOf( \"AppleWebKit\" ) > -1 &&\n\t\t\tua.match( /(BrowserNG|NokiaBrowser)\\/7\\.[0-3]/ );\n})();\n\n// Support conditions that must be met in order to proceed\n// default enhanced qualifications are media query support OR IE 7+\n\n$.mobile.gradeA = function() {\n\treturn ( ( $.support.mediaquery && $.support.cssPseudoElement ) || $.mobile.browser.oldIE && $.mobile.browser.oldIE >= 8 ) && ( $.support.boundingRect || $.fn.jquery.match(/1\\.[0-7+]\\.[0-9+]?/) !== null );\n};\n\n$.mobile.ajaxBlacklist =\n\t\t\t// BlackBerry browsers, pre-webkit\n\t\t\twindow.blackberry && !window.WebKitPoint ||\n\t\t\t// Opera Mini\n\t\t\toperamini ||\n\t\t\t// Symbian webkits pre 7.3\n\t\t\tnokiaLTE7_3;\n\n// Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices\n// to render the stylesheets when they're referenced before this script, as we'd recommend doing.\n// This simply reappends the CSS in place, which for some reason makes it apply\nif ( nokiaLTE7_3 ) {\n\t$(function() {\n\t\t$( \"head link[rel='stylesheet']\" ).attr( \"rel\", \"alternate stylesheet\" ).attr( \"rel\", \"stylesheet\" );\n\t});\n}\n\n// For ruling out shadows via css\nif ( !$.support.boxShadow ) {\n\t$( \"html\" ).addClass( \"ui-noboxshadow\" );\n}\n\n})( jQuery );\n\n\n(function( $, undefined ) {\n\tvar $win = $.mobile.window, self,\n\t\tdummyFnToInitNavigate = function() {\n\t\t};\n\n\t$.event.special.beforenavigate = {\n\t\tsetup: function() {\n\t\t\t$win.on( \"navigate\", dummyFnToInitNavigate );\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t$win.off( \"navigate\", dummyFnToInitNavigate );\n\t\t}\n\t};\n\n\t$.event.special.navigate = self = {\n\t\tbound: false,\n\n\t\tpushStateEnabled: true,\n\n\t\toriginalEventName: undefined,\n\n\t\t// If pushstate support is present and push state support is defined to\n\t\t// be true on the mobile namespace.\n\t\tisPushStateEnabled: function() {\n\t\t\treturn $.support.pushState &&\n\t\t\t\t$.mobile.pushStateEnabled === true &&\n\t\t\t\tthis.isHashChangeEnabled();\n\t\t},\n\n\t\t// !! assumes mobile namespace is present\n\t\tisHashChangeEnabled: function() {\n\t\t\treturn $.mobile.hashListeningEnabled === true;\n\t\t},\n\n\t\t// TODO a lot of duplication between popstate and hashchange\n\t\tpopstate: function( event ) {\n\t\t\tvar newEvent = new $.Event( \"navigate\" ),\n\t\t\t\tbeforeNavigate = new $.Event( \"beforenavigate\" ),\n\t\t\t\tstate = event.originalEvent.state || {};\n\n\t\t\tbeforeNavigate.originalEvent = event;\n\t\t\t$win.trigger( beforeNavigate );\n\n\t\t\tif ( beforeNavigate.isDefaultPrevented() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( event.historyState ) {\n\t\t\t\t$.extend(state, event.historyState);\n\t\t\t}\n\n\t\t\t// Make sure the original event is tracked for the end\n\t\t\t// user to inspect incase they want to do something special\n\t\t\tnewEvent.originalEvent = event;\n\n\t\t\t// NOTE we let the current stack unwind because any assignment to\n\t\t\t//      location.hash will stop the world and run this event handler. By\n\t\t\t//      doing this we create a similar behavior to hashchange on hash\n\t\t\t//      assignment\n\t\t\tsetTimeout(function() {\n\t\t\t\t$win.trigger( newEvent, {\n\t\t\t\t\tstate: state\n\t\t\t\t});\n\t\t\t}, 0);\n\t\t},\n\n\t\thashchange: function( event /*, data */ ) {\n\t\t\tvar newEvent = new $.Event( \"navigate\" ),\n\t\t\t\tbeforeNavigate = new $.Event( \"beforenavigate\" );\n\n\t\t\tbeforeNavigate.originalEvent = event;\n\t\t\t$win.trigger( beforeNavigate );\n\n\t\t\tif ( beforeNavigate.isDefaultPrevented() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Make sure the original event is tracked for the end\n\t\t\t// user to inspect incase they want to do something special\n\t\t\tnewEvent.originalEvent = event;\n\n\t\t\t// Trigger the hashchange with state provided by the user\n\t\t\t// that altered the hash\n\t\t\t$win.trigger( newEvent, {\n\t\t\t\t// Users that want to fully normalize the two events\n\t\t\t\t// will need to do history management down the stack and\n\t\t\t\t// add the state to the event before this binding is fired\n\t\t\t\t// TODO consider allowing for the explicit addition of callbacks\n\t\t\t\t//      to be fired before this value is set to avoid event timing issues\n\t\t\t\tstate: event.hashchangeState || {}\n\t\t\t});\n\t\t},\n\n\t\t// TODO We really only want to set this up once\n\t\t//      but I'm not clear if there's a beter way to achieve\n\t\t//      this with the jQuery special event structure\n\t\tsetup: function( /* data, namespaces */ ) {\n\t\t\tif ( self.bound ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tself.bound = true;\n\n\t\t\tif ( self.isPushStateEnabled() ) {\n\t\t\t\tself.originalEventName = \"popstate\";\n\t\t\t\t$win.bind( \"popstate.navigate\", self.popstate );\n\t\t\t} else if ( self.isHashChangeEnabled() ) {\n\t\t\t\tself.originalEventName = \"hashchange\";\n\t\t\t\t$win.bind( \"hashchange.navigate\", self.hashchange );\n\t\t\t}\n\t\t}\n\t};\n})( jQuery );\n\n\n\n(function( $, undefined ) {\n\t\tvar path, $base, dialogHashKey = \"&ui-state=dialog\";\n\n\t\t$.mobile.path = path = {\n\t\t\tuiStateKey: \"&ui-state\",\n\n\t\t\t// This scary looking regular expression parses an absolute URL or its relative\n\t\t\t// variants (protocol, site, document, query, and hash), into the various\n\t\t\t// components (protocol, host, path, query, fragment, etc that make up the\n\t\t\t// URL as well as some other commonly used sub-parts. When used with RegExp.exec()\n\t\t\t// or String.match, it parses the URL into a results array that looks like this:\n\t\t\t//\n\t\t\t//     [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content\n\t\t\t//     [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread\n\t\t\t//     [2]: http://jblas:password@mycompany.com:8080/mail/inbox\n\t\t\t//     [3]: http://jblas:password@mycompany.com:8080\n\t\t\t//     [4]: http:\n\t\t\t//     [5]: //\n\t\t\t//     [6]: jblas:password@mycompany.com:8080\n\t\t\t//     [7]: jblas:password\n\t\t\t//     [8]: jblas\n\t\t\t//     [9]: password\n\t\t\t//    [10]: mycompany.com:8080\n\t\t\t//    [11]: mycompany.com\n\t\t\t//    [12]: 8080\n\t\t\t//    [13]: /mail/inbox\n\t\t\t//    [14]: /mail/\n\t\t\t//    [15]: inbox\n\t\t\t//    [16]: ?msg=1234&type=unread\n\t\t\t//    [17]: #msg-content\n\t\t\t//\n\t\t\turlParseRE: /^\\s*(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#]*)))?(\\?[^#]+)?)(#.*)?/,\n\n\t\t\t// Abstraction to address xss (Issue #4787) by removing the authority in\n\t\t\t// browsers that auto-decode it. All references to location.href should be\n\t\t\t// replaced with a call to this method so that it can be dealt with properly here\n\t\t\tgetLocation: function( url ) {\n\t\t\t\tvar parsedUrl = this.parseUrl( url || location.href ),\n\t\t\t\t\turi = url ? parsedUrl : location,\n\n\t\t\t\t\t// Make sure to parse the url or the location object for the hash because using\n\t\t\t\t\t// location.hash is autodecoded in firefox, the rest of the url should be from\n\t\t\t\t\t// the object (location unless we're testing) to avoid the inclusion of the\n\t\t\t\t\t// authority\n\t\t\t\t\thash = parsedUrl.hash;\n\n\t\t\t\t// mimic the browser with an empty string when the hash is empty\n\t\t\t\thash = hash === \"#\" ? \"\" : hash;\n\n\t\t\t\treturn uri.protocol +\n\t\t\t\t\tparsedUrl.doubleSlash +\n\t\t\t\t\turi.host +\n\n\t\t\t\t\t// The pathname must start with a slash if there's a protocol, because you\n\t\t\t\t\t// can't have a protocol followed by a relative path. Also, it's impossible to\n\t\t\t\t\t// calculate absolute URLs from relative ones if the absolute one doesn't have\n\t\t\t\t\t// a leading \"/\".\n\t\t\t\t\t( ( uri.protocol !== \"\" && uri.pathname.substring( 0, 1 ) !== \"/\" ) ?\n\t\t\t\t\t\t\"/\" : \"\" ) +\n\t\t\t\t\turi.pathname +\n\t\t\t\t\turi.search +\n\t\t\t\t\thash;\n\t\t\t},\n\n\t\t\t//return the original document url\n\t\t\tgetDocumentUrl: function( asParsedObject ) {\n\t\t\t\treturn asParsedObject ? $.extend( {}, path.documentUrl ) : path.documentUrl.href;\n\t\t\t},\n\n\t\t\tparseLocation: function() {\n\t\t\t\treturn this.parseUrl( this.getLocation() );\n\t\t\t},\n\n\t\t\t//Parse a URL into a structure that allows easy access to\n\t\t\t//all of the URL components by name.\n\t\t\tparseUrl: function( url ) {\n\t\t\t\t// If we're passed an object, we'll assume that it is\n\t\t\t\t// a parsed url object and just return it back to the caller.\n\t\t\t\tif ( $.type( url ) === \"object\" ) {\n\t\t\t\t\treturn url;\n\t\t\t\t}\n\n\t\t\t\tvar matches = path.urlParseRE.exec( url || \"\" ) || [];\n\n\t\t\t\t\t// Create an object that allows the caller to access the sub-matches\n\t\t\t\t\t// by name. Note that IE returns an empty string instead of undefined,\n\t\t\t\t\t// like all other browsers do, so we normalize everything so its consistent\n\t\t\t\t\t// no matter what browser we're running on.\n\t\t\t\t\treturn {\n\t\t\t\t\t\thref:         matches[  0 ] || \"\",\n\t\t\t\t\t\threfNoHash:   matches[  1 ] || \"\",\n\t\t\t\t\t\threfNoSearch: matches[  2 ] || \"\",\n\t\t\t\t\t\tdomain:       matches[  3 ] || \"\",\n\t\t\t\t\t\tprotocol:     matches[  4 ] || \"\",\n\t\t\t\t\t\tdoubleSlash:  matches[  5 ] || \"\",\n\t\t\t\t\t\tauthority:    matches[  6 ] || \"\",\n\t\t\t\t\t\tusername:     matches[  8 ] || \"\",\n\t\t\t\t\t\tpassword:     matches[  9 ] || \"\",\n\t\t\t\t\t\thost:         matches[ 10 ] || \"\",\n\t\t\t\t\t\thostname:     matches[ 11 ] || \"\",\n\t\t\t\t\t\tport:         matches[ 12 ] || \"\",\n\t\t\t\t\t\tpathname:     matches[ 13 ] || \"\",\n\t\t\t\t\t\tdirectory:    matches[ 14 ] || \"\",\n\t\t\t\t\t\tfilename:     matches[ 15 ] || \"\",\n\t\t\t\t\t\tsearch:       matches[ 16 ] || \"\",\n\t\t\t\t\t\thash:         matches[ 17 ] || \"\"\n\t\t\t\t\t};\n\t\t\t},\n\n\t\t\t//Turn relPath into an asbolute path. absPath is\n\t\t\t//an optional absolute path which describes what\n\t\t\t//relPath is relative to.\n\t\t\tmakePathAbsolute: function( relPath, absPath ) {\n\t\t\t\tvar absStack,\n\t\t\t\t\trelStack,\n\t\t\t\t\ti, d;\n\n\t\t\t\tif ( relPath && relPath.charAt( 0 ) === \"/\" ) {\n\t\t\t\t\treturn relPath;\n\t\t\t\t}\n\n\t\t\t\trelPath = relPath || \"\";\n\t\t\t\tabsPath = absPath ? absPath.replace( /^\\/|(\\/[^\\/]*|[^\\/]+)$/g, \"\" ) : \"\";\n\n\t\t\t\tabsStack = absPath ? absPath.split( \"/\" ) : [];\n\t\t\t\trelStack = relPath.split( \"/\" );\n\n\t\t\t\tfor ( i = 0; i < relStack.length; i++ ) {\n\t\t\t\t\td = relStack[ i ];\n\t\t\t\t\tswitch ( d ) {\n\t\t\t\t\t\tcase \".\":\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"..\":\n\t\t\t\t\t\t\tif ( absStack.length ) {\n\t\t\t\t\t\t\t\tabsStack.pop();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tabsStack.push( d );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn \"/\" + absStack.join( \"/\" );\n\t\t\t},\n\n\t\t\t//Returns true if both urls have the same domain.\n\t\t\tisSameDomain: function( absUrl1, absUrl2 ) {\n\t\t\t\treturn path.parseUrl( absUrl1 ).domain.toLowerCase() ===\n\t\t\t\t\tpath.parseUrl( absUrl2 ).domain.toLowerCase();\n\t\t\t},\n\n\t\t\t//Returns true for any relative variant.\n\t\t\tisRelativeUrl: function( url ) {\n\t\t\t\t// All relative Url variants have one thing in common, no protocol.\n\t\t\t\treturn path.parseUrl( url ).protocol === \"\";\n\t\t\t},\n\n\t\t\t//Returns true for an absolute url.\n\t\t\tisAbsoluteUrl: function( url ) {\n\t\t\t\treturn path.parseUrl( url ).protocol !== \"\";\n\t\t\t},\n\n\t\t\t//Turn the specified realtive URL into an absolute one. This function\n\t\t\t//can handle all relative variants (protocol, site, document, query, fragment).\n\t\t\tmakeUrlAbsolute: function( relUrl, absUrl ) {\n\t\t\t\tif ( !path.isRelativeUrl( relUrl ) ) {\n\t\t\t\t\treturn relUrl;\n\t\t\t\t}\n\n\t\t\t\tif ( absUrl === undefined ) {\n\t\t\t\t\tabsUrl = this.documentBase;\n\t\t\t\t}\n\n\t\t\t\tvar relObj = path.parseUrl( relUrl ),\n\t\t\t\t\tabsObj = path.parseUrl( absUrl ),\n\t\t\t\t\tprotocol = relObj.protocol || absObj.protocol,\n\t\t\t\t\tdoubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash ),\n\t\t\t\t\tauthority = relObj.authority || absObj.authority,\n\t\t\t\t\thasPath = relObj.pathname !== \"\",\n\t\t\t\t\tpathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),\n\t\t\t\t\tsearch = relObj.search || ( !hasPath && absObj.search ) || \"\",\n\t\t\t\t\thash = relObj.hash;\n\n\t\t\t\treturn protocol + doubleSlash + authority + pathname + search + hash;\n\t\t\t},\n\n\t\t\t//Add search (aka query) params to the specified url.\n\t\t\taddSearchParams: function( url, params ) {\n\t\t\t\tvar u = path.parseUrl( url ),\n\t\t\t\t\tp = ( typeof params === \"object\" ) ? $.param( params ) : params,\n\t\t\t\t\ts = u.search || \"?\";\n\t\t\t\treturn u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== \"?\" ? \"&\" : \"\" ) + p + ( u.hash || \"\" );\n\t\t\t},\n\n\t\t\tconvertUrlToDataUrl: function( absUrl ) {\n\t\t\t\tvar result = absUrl,\n\t\t\t\t\tu = path.parseUrl( absUrl );\n\n\t\t\t\tif ( path.isEmbeddedPage( u ) ) {\n\t\t\t\t\t// For embedded pages, remove the dialog hash key as in getFilePath(),\n\t\t\t\t\t// and remove otherwise the Data Url won't match the id of the embedded Page.\n\t\t\t\t\tresult = u.hash\n\t\t\t\t\t\t.split( dialogHashKey )[0]\n\t\t\t\t\t\t.replace( /^#/, \"\" )\n\t\t\t\t\t\t.replace( /\\?.*$/, \"\" );\n\t\t\t\t} else if ( path.isSameDomain( u, this.documentBase ) ) {\n\t\t\t\t\tresult = u.hrefNoHash.replace( this.documentBase.domain, \"\" ).split( dialogHashKey )[0];\n\t\t\t\t}\n\n\t\t\t\treturn window.decodeURIComponent( result );\n\t\t\t},\n\n\t\t\t//get path from current hash, or from a file path\n\t\t\tget: function( newPath ) {\n\t\t\t\tif ( newPath === undefined ) {\n\t\t\t\t\tnewPath = path.parseLocation().hash;\n\t\t\t\t}\n\t\t\t\treturn path.stripHash( newPath ).replace( /[^\\/]*\\.[^\\/*]+$/, \"\" );\n\t\t\t},\n\n\t\t\t//set location hash to path\n\t\t\tset: function( path ) {\n\t\t\t\tlocation.hash = path;\n\t\t\t},\n\n\t\t\t//test if a given url (string) is a path\n\t\t\t//NOTE might be exceptionally naive\n\t\t\tisPath: function( url ) {\n\t\t\t\treturn ( /\\// ).test( url );\n\t\t\t},\n\n\t\t\t//return a url path with the window's location protocol/hostname/pathname removed\n\t\t\tclean: function( url ) {\n\t\t\t\treturn url.replace( this.documentBase.domain, \"\" );\n\t\t\t},\n\n\t\t\t//just return the url without an initial #\n\t\t\tstripHash: function( url ) {\n\t\t\t\treturn url.replace( /^#/, \"\" );\n\t\t\t},\n\n\t\t\tstripQueryParams: function( url ) {\n\t\t\t\treturn url.replace( /\\?.*$/, \"\" );\n\t\t\t},\n\n\t\t\t//remove the preceding hash, any query params, and dialog notations\n\t\t\tcleanHash: function( hash ) {\n\t\t\t\treturn path.stripHash( hash.replace( /\\?.*$/, \"\" ).replace( dialogHashKey, \"\" ) );\n\t\t\t},\n\n\t\t\tisHashValid: function( hash ) {\n\t\t\t\treturn ( /^#[^#]+$/ ).test( hash );\n\t\t\t},\n\n\t\t\t//check whether a url is referencing the same domain, or an external domain or different protocol\n\t\t\t//could be mailto, etc\n\t\t\tisExternal: function( url ) {\n\t\t\t\tvar u = path.parseUrl( url );\n\n\t\t\t\treturn !!( u.protocol &&\n\t\t\t\t\t( u.domain.toLowerCase() !== this.documentUrl.domain.toLowerCase() ) );\n\t\t\t},\n\n\t\t\thasProtocol: function( url ) {\n\t\t\t\treturn ( /^(:?\\w+:)/ ).test( url );\n\t\t\t},\n\n\t\t\tisEmbeddedPage: function( url ) {\n\t\t\t\tvar u = path.parseUrl( url );\n\n\t\t\t\t//if the path is absolute, then we need to compare the url against\n\t\t\t\t//both the this.documentUrl and the documentBase. The main reason for this\n\t\t\t\t//is that links embedded within external documents will refer to the\n\t\t\t\t//application document, whereas links embedded within the application\n\t\t\t\t//document will be resolved against the document base.\n\t\t\t\tif ( u.protocol !== \"\" ) {\n\t\t\t\t\treturn ( !this.isPath(u.hash) && u.hash && ( u.hrefNoHash === this.documentUrl.hrefNoHash || ( this.documentBaseDiffers && u.hrefNoHash === this.documentBase.hrefNoHash ) ) );\n\t\t\t\t}\n\t\t\t\treturn ( /^#/ ).test( u.href );\n\t\t\t},\n\n\t\t\tsquash: function( url, resolutionUrl ) {\n\t\t\t\tvar href, cleanedUrl, search, stateIndex, docUrl,\n\t\t\t\t\tisPath = this.isPath( url ),\n\t\t\t\t\turi = this.parseUrl( url ),\n\t\t\t\t\tpreservedHash = uri.hash,\n\t\t\t\t\tuiState = \"\";\n\n\t\t\t\t// produce a url against which we can resolve the provided path\n\t\t\t\tif ( !resolutionUrl ) {\n\t\t\t\t\tif ( isPath ) {\n\t\t\t\t\t\tresolutionUrl = path.getLocation();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdocUrl = path.getDocumentUrl( true );\n\t\t\t\t\t\tif ( path.isPath( docUrl.hash ) ) {\n\t\t\t\t\t\t\tresolutionUrl = path.squash( docUrl.href );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolutionUrl = docUrl.href;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If the url is anything but a simple string, remove any preceding hash\n\t\t\t\t// eg #foo/bar -> foo/bar\n\t\t\t\t//    #foo -> #foo\n\t\t\t\tcleanedUrl = isPath ? path.stripHash( url ) : url;\n\n\t\t\t\t// If the url is a full url with a hash check if the parsed hash is a path\n\t\t\t\t// if it is, strip the #, and use it otherwise continue without change\n\t\t\t\tcleanedUrl = path.isPath( uri.hash ) ? path.stripHash( uri.hash ) : cleanedUrl;\n\n\t\t\t\t// Split the UI State keys off the href\n\t\t\t\tstateIndex = cleanedUrl.indexOf( this.uiStateKey );\n\n\t\t\t\t// store the ui state keys for use\n\t\t\t\tif ( stateIndex > -1 ) {\n\t\t\t\t\tuiState = cleanedUrl.slice( stateIndex );\n\t\t\t\t\tcleanedUrl = cleanedUrl.slice( 0, stateIndex );\n\t\t\t\t}\n\n\t\t\t\t// make the cleanedUrl absolute relative to the resolution url\n\t\t\t\thref = path.makeUrlAbsolute( cleanedUrl, resolutionUrl );\n\n\t\t\t\t// grab the search from the resolved url since parsing from\n\t\t\t\t// the passed url may not yield the correct result\n\t\t\t\tsearch = this.parseUrl( href ).search;\n\n\t\t\t\t// TODO all this crap is terrible, clean it up\n\t\t\t\tif ( isPath ) {\n\t\t\t\t\t// reject the hash if it's a path or it's just a dialog key\n\t\t\t\t\tif ( path.isPath( preservedHash ) || preservedHash.replace(\"#\", \"\").indexOf( this.uiStateKey ) === 0) {\n\t\t\t\t\t\tpreservedHash = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Append the UI State keys where it exists and it's been removed\n\t\t\t\t\t// from the url\n\t\t\t\t\tif ( uiState && preservedHash.indexOf( this.uiStateKey ) === -1) {\n\t\t\t\t\t\tpreservedHash += uiState;\n\t\t\t\t\t}\n\n\t\t\t\t\t// make sure that pound is on the front of the hash\n\t\t\t\t\tif ( preservedHash.indexOf( \"#\" ) === -1 && preservedHash !== \"\" ) {\n\t\t\t\t\t\tpreservedHash = \"#\" + preservedHash;\n\t\t\t\t\t}\n\n\t\t\t\t\t// reconstruct each of the pieces with the new search string and hash\n\t\t\t\t\thref = path.parseUrl( href );\n\t\t\t\t\thref = href.protocol + href.doubleSlash + href.host + href.pathname + search +\n\t\t\t\t\t\tpreservedHash;\n\t\t\t\t} else {\n\t\t\t\t\thref += href.indexOf( \"#\" ) > -1 ? uiState : \"#\" + uiState;\n\t\t\t\t}\n\n\t\t\t\treturn href;\n\t\t\t},\n\n\t\t\tisPreservableHash: function( hash ) {\n\t\t\t\treturn hash.replace( \"#\", \"\" ).indexOf( this.uiStateKey ) === 0;\n\t\t\t},\n\n\t\t\t// Escape weird characters in the hash if it is to be used as a selector\n\t\t\thashToSelector: function( hash ) {\n\t\t\t\tvar hasHash = ( hash.substring( 0, 1 ) === \"#\" );\n\t\t\t\tif ( hasHash ) {\n\t\t\t\t\thash = hash.substring( 1 );\n\t\t\t\t}\n\t\t\t\treturn ( hasHash ? \"#\" : \"\" ) + hash.replace( /([!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~])/g, \"\\\\$1\" );\n\t\t\t},\n\n\t\t\t// return the substring of a filepath before the dialogHashKey, for making a server\n\t\t\t// request\n\t\t\tgetFilePath: function( path ) {\n\t\t\t\treturn path && path.split( dialogHashKey )[0];\n\t\t\t},\n\n\t\t\t// check if the specified url refers to the first page in the main\n\t\t\t// application document.\n\t\t\tisFirstPageUrl: function( url ) {\n\t\t\t\t// We only deal with absolute paths.\n\t\t\t\tvar u = path.parseUrl( path.makeUrlAbsolute( url, this.documentBase ) ),\n\n\t\t\t\t\t// Does the url have the same path as the document?\n\t\t\t\t\tsamePath = u.hrefNoHash === this.documentUrl.hrefNoHash ||\n\t\t\t\t\t\t( this.documentBaseDiffers &&\n\t\t\t\t\t\t\tu.hrefNoHash === this.documentBase.hrefNoHash ),\n\n\t\t\t\t\t// Get the first page element.\n\t\t\t\t\tfp = $.mobile.firstPage,\n\n\t\t\t\t\t// Get the id of the first page element if it has one.\n\t\t\t\t\tfpId = fp && fp[0] ? fp[0].id : undefined;\n\n\t\t\t\t// The url refers to the first page if the path matches the document and\n\t\t\t\t// it either has no hash value, or the hash is exactly equal to the id\n\t\t\t\t// of the first page element.\n\t\t\t\treturn samePath &&\n\t\t\t\t\t( !u.hash ||\n\t\t\t\t\t\tu.hash === \"#\" ||\n\t\t\t\t\t\t( fpId && u.hash.replace( /^#/, \"\" ) === fpId ) );\n\t\t\t},\n\n\t\t\t// Some embedded browsers, like the web view in Phone Gap, allow\n\t\t\t// cross-domain XHR requests if the document doing the request was loaded\n\t\t\t// via the file:// protocol. This is usually to allow the application to\n\t\t\t// \"phone home\" and fetch app specific data. We normally let the browser\n\t\t\t// handle external/cross-domain urls, but if the allowCrossDomainPages\n\t\t\t// option is true, we will allow cross-domain http/https requests to go\n\t\t\t// through our page loading logic.\n\t\t\tisPermittedCrossDomainRequest: function( docUrl, reqUrl ) {\n\t\t\t\treturn $.mobile.allowCrossDomainPages &&\n\t\t\t\t\t(docUrl.protocol === \"file:\" || docUrl.protocol === \"content:\") &&\n\t\t\t\t\treqUrl.search( /^https?:/ ) !== -1;\n\t\t\t}\n\t\t};\n\n\t\tpath.documentUrl = path.parseLocation();\n\n\t\t$base = $( \"head\" ).find( \"base\" );\n\n\t\tpath.documentBase = $base.length ?\n\t\t\tpath.parseUrl( path.makeUrlAbsolute( $base.attr( \"href\" ), path.documentUrl.href ) ) :\n\t\t\tpath.documentUrl;\n\n\t\tpath.documentBaseDiffers = (path.documentUrl.hrefNoHash !== path.documentBase.hrefNoHash);\n\n\t\t//return the original document base url\n\t\tpath.getDocumentBase = function( asParsedObject ) {\n\t\t\treturn asParsedObject ? $.extend( {}, path.documentBase ) : path.documentBase.href;\n\t\t};\n\n\t\t// DEPRECATED as of 1.4.0 - remove in 1.5.0\n\t\t$.extend( $.mobile, {\n\n\t\t\t//return the original document url\n\t\t\tgetDocumentUrl: path.getDocumentUrl,\n\n\t\t\t//return the original document base url\n\t\t\tgetDocumentBase: path.getDocumentBase\n\t\t});\n})( jQuery );\n\n\n\n(function( $, undefined ) {\n\t$.mobile.History = function( stack, index ) {\n\t\tthis.stack = stack || [];\n\t\tthis.activeIndex = index || 0;\n\t};\n\n\t$.extend($.mobile.History.prototype, {\n\t\tgetActive: function() {\n\t\t\treturn this.stack[ this.activeIndex ];\n\t\t},\n\n\t\tgetLast: function() {\n\t\t\treturn this.stack[ this.previousIndex ];\n\t\t},\n\n\t\tgetNext: function() {\n\t\t\treturn this.stack[ this.activeIndex + 1 ];\n\t\t},\n\n\t\tgetPrev: function() {\n\t\t\treturn this.stack[ this.activeIndex - 1 ];\n\t\t},\n\n\t\t// addNew is used whenever a new page is added\n\t\tadd: function( url, data ) {\n\t\t\tdata = data || {};\n\n\t\t\t//if there's forward history, wipe it\n\t\t\tif ( this.getNext() ) {\n\t\t\t\tthis.clearForward();\n\t\t\t}\n\n\t\t\t// if the hash is included in the data make sure the shape\n\t\t\t// is consistent for comparison\n\t\t\tif ( data.hash && data.hash.indexOf( \"#\" ) === -1) {\n\t\t\t\tdata.hash = \"#\" + data.hash;\n\t\t\t}\n\n\t\t\tdata.url = url;\n\t\t\tthis.stack.push( data );\n\t\t\tthis.activeIndex = this.stack.length - 1;\n\t\t},\n\n\t\t//wipe urls ahead of active index\n\t\tclearForward: function() {\n\t\t\tthis.stack = this.stack.slice( 0, this.activeIndex + 1 );\n\t\t},\n\n\t\tfind: function( url, stack, earlyReturn ) {\n\t\t\tstack = stack || this.stack;\n\n\t\t\tvar entry, i, length = stack.length, index;\n\n\t\t\tfor ( i = 0; i < length; i++ ) {\n\t\t\t\tentry = stack[i];\n\n\t\t\t\tif ( decodeURIComponent(url) === decodeURIComponent(entry.url) ||\n\t\t\t\t\tdecodeURIComponent(url) === decodeURIComponent(entry.hash) ) {\n\t\t\t\t\tindex = i;\n\n\t\t\t\t\tif ( earlyReturn ) {\n\t\t\t\t\t\treturn index;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn index;\n\t\t},\n\n\t\tclosest: function( url ) {\n\t\t\tvar closest, a = this.activeIndex;\n\n\t\t\t// First, take the slice of the history stack before the current index and search\n\t\t\t// for a url match. If one is found, we'll avoid avoid looking through forward history\n\t\t\t// NOTE the preference for backward history movement is driven by the fact that\n\t\t\t//      most mobile browsers only have a dedicated back button, and users rarely use\n\t\t\t//      the forward button in desktop browser anyhow\n\t\t\tclosest = this.find( url, this.stack.slice(0, a) );\n\n\t\t\t// If nothing was found in backward history check forward. The `true`\n\t\t\t// value passed as the third parameter causes the find method to break\n\t\t\t// on the first match in the forward history slice. The starting index\n\t\t\t// of the slice must then be added to the result to get the element index\n\t\t\t// in the original history stack :( :(\n\t\t\t//\n\t\t\t// TODO this is hyper confusing and should be cleaned up (ugh so bad)\n\t\t\tif ( closest === undefined ) {\n\t\t\t\tclosest = this.find( url, this.stack.slice(a), true );\n\t\t\t\tclosest = closest === undefined ? closest : closest + a;\n\t\t\t}\n\n\t\t\treturn closest;\n\t\t},\n\n\t\tdirect: function( opts ) {\n\t\t\tvar newActiveIndex = this.closest( opts.url ), a = this.activeIndex;\n\n\t\t\t// save new page index, null check to prevent falsey 0 result\n\t\t\t// record the previous index for reference\n\t\t\tif ( newActiveIndex !== undefined ) {\n\t\t\t\tthis.activeIndex = newActiveIndex;\n\t\t\t\tthis.previousIndex = a;\n\t\t\t}\n\n\t\t\t// invoke callbacks where appropriate\n\t\t\t//\n\t\t\t// TODO this is also convoluted and confusing\n\t\t\tif ( newActiveIndex < a ) {\n\t\t\t\t( opts.present || opts.back || $.noop )( this.getActive(), \"back\" );\n\t\t\t} else if ( newActiveIndex > a ) {\n\t\t\t\t( opts.present || opts.forward || $.noop )( this.getActive(), \"forward\" );\n\t\t\t} else if ( newActiveIndex === undefined && opts.missing ) {\n\t\t\t\topts.missing( this.getActive() );\n\t\t\t}\n\t\t}\n\t});\n})( jQuery );\n\n\n\n(function( $, undefined ) {\n\tvar path = $.mobile.path,\n\t\tinitialHref = location.href;\n\n\t$.mobile.Navigator = function( history ) {\n\t\tthis.history = history;\n\t\tthis.ignoreInitialHashChange = true;\n\n\t\t$.mobile.window.bind({\n\t\t\t\"popstate.history\": $.proxy( this.popstate, this ),\n\t\t\t\"hashchange.history\": $.proxy( this.hashchange, this )\n\t\t});\n\t};\n\n\t$.extend($.mobile.Navigator.prototype, {\n\t\tsquash: function( url, data ) {\n\t\t\tvar state, href, hash = path.isPath(url) ? path.stripHash(url) : url;\n\n\t\t\thref = path.squash( url );\n\n\t\t\t// make sure to provide this information when it isn't explicitly set in the\n\t\t\t// data object that was passed to the squash method\n\t\t\tstate = $.extend({\n\t\t\t\thash: hash,\n\t\t\t\turl: href\n\t\t\t}, data);\n\n\t\t\t// replace the current url with the new href and store the state\n\t\t\t// Note that in some cases we might be replacing an url with the\n\t\t\t// same url. We do this anyways because we need to make sure that\n\t\t\t// all of our history entries have a state object associated with\n\t\t\t// them. This allows us to work around the case where $.mobile.back()\n\t\t\t// is called to transition from an external page to an embedded page.\n\t\t\t// In that particular case, a hashchange event is *NOT* generated by the browser.\n\t\t\t// Ensuring each history entry has a state object means that onPopState()\n\t\t\t// will always trigger our hashchange callback even when a hashchange event\n\t\t\t// is not fired.\n\t\t\twindow.history.replaceState( state, state.title || document.title, href );\n\n\t\t\treturn state;\n\t\t},\n\n\t\thash: function( url, href ) {\n\t\t\tvar parsed, loc, hash, resolved;\n\n\t\t\t// Grab the hash for recording. If the passed url is a path\n\t\t\t// we used the parsed version of the squashed url to reconstruct,\n\t\t\t// otherwise we assume it's a hash and store it directly\n\t\t\tparsed = path.parseUrl( url );\n\t\t\tloc = path.parseLocation();\n\n\t\t\tif ( loc.pathname + loc.search === parsed.pathname + parsed.search ) {\n\t\t\t\t// If the pathname and search of the passed url is identical to the current loc\n\t\t\t\t// then we must use the hash. Otherwise there will be no event\n\t\t\t\t// eg, url = \"/foo/bar?baz#bang\", location.href = \"http://example.com/foo/bar?baz\"\n\t\t\t\thash = parsed.hash ? parsed.hash : parsed.pathname + parsed.search;\n\t\t\t} else if ( path.isPath(url) ) {\n\t\t\t\tresolved = path.parseUrl( href );\n\t\t\t\t// If the passed url is a path, make it domain relative and remove any trailing hash\n\t\t\t\thash = resolved.pathname + resolved.search + (path.isPreservableHash( resolved.hash )? resolved.hash.replace( \"#\", \"\" ) : \"\");\n\t\t\t} else {\n\t\t\t\thash = url;\n\t\t\t}\n\n\t\t\treturn hash;\n\t\t},\n\n\t\t// TODO reconsider name\n\t\tgo: function( url, data, noEvents ) {\n\t\t\tvar state, href, hash, popstateEvent,\n\t\t\t\tisPopStateEvent = $.event.special.navigate.isPushStateEnabled();\n\n\t\t\t// Get the url as it would look squashed on to the current resolution url\n\t\t\thref = path.squash( url );\n\n\t\t\t// sort out what the hash sould be from the url\n\t\t\thash = this.hash( url, href );\n\n\t\t\t// Here we prevent the next hash change or popstate event from doing any\n\t\t\t// history management. In the case of hashchange we don't swallow it\n\t\t\t// if there will be no hashchange fired (since that won't reset the value)\n\t\t\t// and will swallow the following hashchange\n\t\t\tif ( noEvents && hash !== path.stripHash(path.parseLocation().hash) ) {\n\t\t\t\tthis.preventNextHashChange = noEvents;\n\t\t\t}\n\n\t\t\t// IMPORTANT in the case where popstate is supported the event will be triggered\n\t\t\t//      directly, stopping further execution - ie, interupting the flow of this\n\t\t\t//      method call to fire bindings at this expression. Below the navigate method\n\t\t\t//      there is a binding to catch this event and stop its propagation.\n\t\t\t//\n\t\t\t//      We then trigger a new popstate event on the window with a null state\n\t\t\t//      so that the navigate events can conclude their work properly\n\t\t\t//\n\t\t\t// if the url is a path we want to preserve the query params that are available on\n\t\t\t// the current url.\n\t\t\tthis.preventHashAssignPopState = true;\n\t\t\twindow.location.hash = hash;\n\n\t\t\t// If popstate is enabled and the browser triggers `popstate` events when the hash\n\t\t\t// is set (this often happens immediately in browsers like Chrome), then the\n\t\t\t// this flag will be set to false already. If it's a browser that does not trigger\n\t\t\t// a `popstate` on hash assignement or `replaceState` then we need avoid the branch\n\t\t\t// that swallows the event created by the popstate generated by the hash assignment\n\t\t\t// At the time of this writing this happens with Opera 12 and some version of IE\n\t\t\tthis.preventHashAssignPopState = false;\n\n\t\t\tstate = $.extend({\n\t\t\t\turl: href,\n\t\t\t\thash: hash,\n\t\t\t\ttitle: document.title\n\t\t\t}, data);\n\n\t\t\tif ( isPopStateEvent ) {\n\t\t\t\tpopstateEvent = new $.Event( \"popstate\" );\n\t\t\t\tpopstateEvent.originalEvent = {\n\t\t\t\t\ttype: \"popstate\",\n\t\t\t\t\tstate: null\n\t\t\t\t};\n\n\t\t\t\tthis.squash( url, state );\n\n\t\t\t\t// Trigger a new faux popstate event to replace the one that we\n\t\t\t\t// caught that was triggered by the hash setting above.\n\t\t\t\tif ( !noEvents ) {\n\t\t\t\t\tthis.ignorePopState = true;\n\t\t\t\t\t$.mobile.window.trigger( popstateEvent );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// record the history entry so that the information can be included\n\t\t\t// in hashchange event driven navigate events in a similar fashion to\n\t\t\t// the state that's provided by popstate\n\t\t\tthis.history.add( state.url, state );\n\t\t},\n\n\t\t// This binding is intended to catch the popstate events that are fired\n\t\t// when execution of the `$.navigate` method stops at window.location.hash = url;\n\t\t// and completely prevent them from propagating. The popstate event will then be\n\t\t// retriggered after execution resumes\n\t\t//\n\t\t// TODO grab the original event here and use it for the synthetic event in the\n\t\t//      second half of the navigate execution that will follow this binding\n\t\tpopstate: function( event ) {\n\t\t\tvar hash, state;\n\n\t\t\t// Partly to support our test suite which manually alters the support\n\t\t\t// value to test hashchange. Partly to prevent all around weirdness\n\t\t\tif ( !$.event.special.navigate.isPushStateEnabled() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If this is the popstate triggered by the actual alteration of the hash\n\t\t\t// prevent it completely. History is tracked manually\n\t\t\tif ( this.preventHashAssignPopState ) {\n\t\t\t\tthis.preventHashAssignPopState = false;\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// if this is the popstate triggered after the `replaceState` call in the go\n\t\t\t// method, then simply ignore it. The history entry has already been captured\n\t\t\tif ( this.ignorePopState ) {\n\t\t\t\tthis.ignorePopState = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there is no state, and the history stack length is one were\n\t\t\t// probably getting the page load popstate fired by browsers like chrome\n\t\t\t// avoid it and set the one time flag to false.\n\t\t\t// TODO: Do we really need all these conditions? Comparing location hrefs\n\t\t\t// should be sufficient.\n\t\t\tif ( !event.originalEvent.state &&\n\t\t\t\tthis.history.stack.length === 1 &&\n\t\t\t\tthis.ignoreInitialHashChange ) {\n\t\t\t\tthis.ignoreInitialHashChange = false;\n\n\t\t\t\tif ( location.href === initialHref ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// account for direct manipulation of the hash. That is, we will receive a popstate\n\t\t\t// when the hash is changed by assignment, and it won't have a state associated. We\n\t\t\t// then need to squash the hash. See below for handling of hash assignment that\n\t\t\t// matches an existing history entry\n\t\t\t// TODO it might be better to only add to the history stack\n\t\t\t//      when the hash is adjacent to the active history entry\n\t\t\thash = path.parseLocation().hash;\n\t\t\tif ( !event.originalEvent.state && hash ) {\n\t\t\t\t// squash the hash that's been assigned on the URL with replaceState\n\t\t\t\t// also grab the resulting state object for storage\n\t\t\t\tstate = this.squash( hash );\n\n\t\t\t\t// record the new hash as an additional history entry\n\t\t\t\t// to match the browser's treatment of hash assignment\n\t\t\t\tthis.history.add( state.url, state );\n\n\t\t\t\t// pass the newly created state information\n\t\t\t\t// along with the event\n\t\t\t\tevent.historyState = state;\n\n\t\t\t\t// do not alter history, we've added a new history entry\n\t\t\t\t// so we know where we are\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If all else fails this is a popstate that comes from the back or forward buttons\n\t\t\t// make sure to set the state of our history stack properly, and record the directionality\n\t\t\tthis.history.direct({\n\t\t\t\turl: (event.originalEvent.state || {}).url || hash,\n\n\t\t\t\t// When the url is either forward or backward in history include the entry\n\t\t\t\t// as data on the event object for merging as data in the navigate event\n\t\t\t\tpresent: function( historyEntry, direction ) {\n\t\t\t\t\t// make sure to create a new object to pass down as the navigate event data\n\t\t\t\t\tevent.historyState = $.extend({}, historyEntry);\n\t\t\t\t\tevent.historyState.direction = direction;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\t// NOTE must bind before `navigate` special event hashchange binding otherwise the\n\t\t//      navigation data won't be attached to the hashchange event in time for those\n\t\t//      bindings to attach it to the `navigate` special event\n\t\t// TODO add a check here that `hashchange.navigate` is bound already otherwise it's\n\t\t//      broken (exception?)\n\t\thashchange: function( event ) {\n\t\t\tvar history, hash;\n\n\t\t\t// If hashchange listening is explicitly disabled or pushstate is supported\n\t\t\t// avoid making use of the hashchange handler.\n\t\t\tif (!$.event.special.navigate.isHashChangeEnabled() ||\n\t\t\t\t$.event.special.navigate.isPushStateEnabled() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// On occasion explicitly want to prevent the next hash from propogating because we only\n\t\t\t// with to alter the url to represent the new state do so here\n\t\t\tif ( this.preventNextHashChange ) {\n\t\t\t\tthis.preventNextHashChange = false;\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thistory = this.history;\n\t\t\thash = path.parseLocation().hash;\n\n\t\t\t// If this is a hashchange caused by the back or forward button\n\t\t\t// make sure to set the state of our history stack properly\n\t\t\tthis.history.direct({\n\t\t\t\turl: hash,\n\n\t\t\t\t// When the url is either forward or backward in history include the entry\n\t\t\t\t// as data on the event object for merging as data in the navigate event\n\t\t\t\tpresent: function( historyEntry, direction ) {\n\t\t\t\t\t// make sure to create a new object to pass down as the navigate event data\n\t\t\t\t\tevent.hashchangeState = $.extend({}, historyEntry);\n\t\t\t\t\tevent.hashchangeState.direction = direction;\n\t\t\t\t},\n\n\t\t\t\t// When we don't find a hash in our history clearly we're aiming to go there\n\t\t\t\t// record the entry as new for future traversal\n\t\t\t\t//\n\t\t\t\t// NOTE it's not entirely clear that this is the right thing to do given that we\n\t\t\t\t//      can't know the users intention. It might be better to explicitly _not_\n\t\t\t\t//      support location.hash assignment in preference to $.navigate calls\n\t\t\t\t// TODO first arg to add should be the href, but it causes issues in identifying\n\t\t\t\t//      embeded pages\n\t\t\t\tmissing: function() {\n\t\t\t\t\thistory.add( hash, {\n\t\t\t\t\t\thash: hash,\n\t\t\t\t\t\ttitle: document.title\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n})( jQuery );\n\n\n\n(function( $, undefined ) {\n\t// TODO consider queueing navigation activity until previous activities have completed\n\t//      so that end users don't have to think about it. Punting for now\n\t// TODO !! move the event bindings into callbacks on the navigate event\n\t$.mobile.navigate = function( url, data, noEvents ) {\n\t\t$.mobile.navigate.navigator.go( url, data, noEvents );\n\t};\n\n\t// expose the history on the navigate method in anticipation of full integration with\n\t// existing navigation functionalty that is tightly coupled to the history information\n\t$.mobile.navigate.history = new $.mobile.History();\n\n\t// instantiate an instance of the navigator for use within the $.navigate method\n\t$.mobile.navigate.navigator = new $.mobile.Navigator( $.mobile.navigate.history );\n\n\tvar loc = $.mobile.path.parseLocation();\n\t$.mobile.navigate.history.add( loc.href, {hash: loc.hash} );\n})( jQuery );\n\n\n(function( $, undefined ) {\n\tvar props = {\n\t\t\t\"animation\": {},\n\t\t\t\"transition\": {}\n\t\t},\n\t\ttestElement = document.createElement( \"a\" ),\n\t\tvendorPrefixes = [ \"\", \"webkit-\", \"moz-\", \"o-\" ];\n\n\t$.each( [ \"animation\", \"transition\" ], function( i, test ) {\n\n\t\t// Get correct name for test\n\t\tvar testName = ( i === 0 ) ? test + \"-\" + \"name\" : test;\n\n\t\t$.each( vendorPrefixes, function( j, prefix ) {\n\t\t\tif ( testElement.style[ $.camelCase( prefix + testName ) ] !== undefined ) {\n\t\t\t\t props[ test ][ \"prefix\" ] = prefix;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\n\t\t// Set event and duration names for later use\n\t\tprops[ test ][ \"duration\" ] =\n\t\t\t$.camelCase( props[ test ][ \"prefix\" ] + test + \"-\" + \"duration\" );\n\t\tprops[ test ][ \"event\" ] =\n\t\t\t$.camelCase( props[ test ][ \"prefix\" ] + test + \"-\" + \"end\" );\n\n\t\t// All lower case if not a vendor prop\n\t\tif ( props[ test ][ \"prefix\" ] === \"\" ) {\n\t\t\tprops[ test ][ \"event\" ] = props[ test ][ \"event\" ].toLowerCase();\n\t\t}\n\t});\n\n\t// If a valid prefix was found then the it is supported by the browser\n\t$.support.cssTransitions = ( props[ \"transition\" ][ \"prefix\" ] !== undefined );\n\t$.support.cssAnimations = ( props[ \"animation\" ][ \"prefix\" ] !== undefined );\n\n\t// Remove the testElement\n\t$( testElement ).remove();\n\n\t// Animation complete callback\n\t$.fn.animationComplete = function( callback, type, fallbackTime ) {\n\t\tvar timer, duration,\n\t\t\tthat = this,\n\t\t\teventBinding = function() {\n\n\t\t\t\t// Clear the timer so we don't call callback twice\n\t\t\t\tclearTimeout( timer );\n\t\t\t\tcallback.apply( this, arguments );\n\t\t\t},\n\t\t\tanimationType = ( !type || type === \"animation\" ) ? \"animation\" : \"transition\";\n\n\t\t// Make sure selected type is supported by browser\n\t\tif ( ( $.support.cssTransitions && animationType === \"transition\" ) ||\n\t\t\t( $.support.cssAnimations && animationType === \"animation\" ) ) {\n\n\t\t\t// If a fallback time was not passed set one\n\t\t\tif ( fallbackTime === undefined ) {\n\n\t\t\t\t// Make sure the was not bound to document before checking .css\n\t\t\t\tif ( $( this ).context !== document ) {\n\n\t\t\t\t\t// Parse the durration since its in second multiple by 1000 for milliseconds\n\t\t\t\t\t// Multiply by 3 to make sure we give the animation plenty of time.\n\t\t\t\t\tduration = parseFloat(\n\t\t\t\t\t\t$( this ).css( props[ animationType ].duration )\n\t\t\t\t\t) * 3000;\n\t\t\t\t}\n\n\t\t\t\t// If we could not read a duration use the default\n\t\t\t\tif ( duration === 0 || duration === undefined || isNaN( duration ) ) {\n\t\t\t\t\tduration = $.fn.animationComplete.defaultDuration;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Sets up the fallback if event never comes\n\t\t\ttimer = setTimeout( function() {\n\t\t\t\t$( that ).off( props[ animationType ].event, eventBinding );\n\t\t\t\tcallback.apply( that );\n\t\t\t}, duration );\n\n\t\t\t// Bind the event\n\t\t\treturn $( this ).one( props[ animationType ].event, eventBinding );\n\t\t} else {\n\n\t\t\t// CSS animation / transitions not supported\n\t\t\t// Defer execution for consistency between webkit/non webkit\n\t\t\tsetTimeout( $.proxy( callback, this ), 0 );\n\t\t\treturn $( this );\n\t\t}\n\t};\n\n\t// Allow default callback to be configured on mobileInit\n\t$.fn.animationComplete.defaultDuration = 1000;\n})( jQuery );\n\n// This plugin is an experiment for abstracting away the touch and mouse\n// events so that developers don't have to worry about which method of input\n// the device their document is loaded on supports.\n//\n// The idea here is to allow the developer to register listeners for the\n// basic mouse events, such as mousedown, mousemove, mouseup, and click,\n// and the plugin will take care of registering the correct listeners\n// behind the scenes to invoke the listener at the fastest possible time\n// for that device, while still retaining the order of event firing in\n// the traditional mouse environment, should multiple handlers be registered\n// on the same element for different events.\n//\n// The current version exposes the following virtual events to jQuery bind methods:\n// \"vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel\"\n\n(function( $, window, document, undefined ) {\n\nvar dataPropertyName = \"virtualMouseBindings\",\n\ttouchTargetPropertyName = \"virtualTouchID\",\n\tvirtualEventNames = \"vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel\".split( \" \" ),\n\ttouchEventProps = \"clientX clientY pageX pageY screenX screenY\".split( \" \" ),\n\tmouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],\n\tmouseEventProps = $.event.props.concat( mouseHookProps ),\n\tactiveDocHandlers = {},\n\tresetTimerID = 0,\n\tstartX = 0,\n\tstartY = 0,\n\tdidScroll = false,\n\tclickBlockList = [],\n\tblockMouseTriggers = false,\n\tblockTouchTriggers = false,\n\teventCaptureSupported = \"addEventListener\" in document,\n\t$document = $( document ),\n\tnextTouchID = 1,\n\tlastTouchID = 0, threshold,\n\ti;\n\n$.vmouse = {\n\tmoveDistanceThreshold: 10,\n\tclickDistanceThreshold: 10,\n\tresetTimerDuration: 1500\n};\n\nfunction getNativeEvent( event ) {\n\n\twhile ( event && typeof event.originalEvent !== \"undefined\" ) {\n\t\tevent = event.originalEvent;\n\t}\n\treturn event;\n}\n\nfunction createVirtualEvent( event, eventType ) {\n\n\tvar t = event.type,\n\t\toe, props, ne, prop, ct, touch, i, j, len;\n\n\tevent = $.Event( event );\n\tevent.type = eventType;\n\n\toe = event.originalEvent;\n\tprops = $.event.props;\n\n\t// addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280\n\t// https://github.com/jquery/jquery-mobile/issues/3280\n\tif ( t.search( /^(mouse|click)/ ) > -1 ) {\n\t\tprops = mouseEventProps;\n\t}\n\n\t// copy original event properties over to the new event\n\t// this would happen if we could call $.event.fix instead of $.Event\n\t// but we don't have a way to force an event to be fixed multiple times\n\tif ( oe ) {\n\t\tfor ( i = props.length, prop; i; ) {\n\t\t\tprop = props[ --i ];\n\t\t\tevent[ prop ] = oe[ prop ];\n\t\t}\n\t}\n\n\t// make sure that if the mouse and click virtual events are generated\n\t// without a .which one is defined\n\tif ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {\n\t\tevent.which = 1;\n\t}\n\n\tif ( t.search(/^touch/) !== -1 ) {\n\t\tne = getNativeEvent( oe );\n\t\tt = ne.touches;\n\t\tct = ne.changedTouches;\n\t\ttouch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );\n\n\t\tif ( touch ) {\n\t\t\tfor ( j = 0, len = touchEventProps.length; j < len; j++) {\n\t\t\t\tprop = touchEventProps[ j ];\n\t\t\t\tevent[ prop ] = touch[ prop ];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn event;\n}\n\nfunction getVirtualBindingFlags( element ) {\n\n\tvar flags = {},\n\t\tb, k;\n\n\twhile ( element ) {\n\n\t\tb = $.data( element, dataPropertyName );\n\n\t\tfor (  k in b ) {\n\t\t\tif ( b[ k ] ) {\n\t\t\t\tflags[ k ] = flags.hasVirtualBinding = true;\n\t\t\t}\n\t\t}\n\t\telement = element.parentNode;\n\t}\n\treturn flags;\n}\n\nfunction getClosestElementWithVirtualBinding( element, eventType ) {\n\tvar b;\n\twhile ( element ) {\n\n\t\tb = $.data( element, dataPropertyName );\n\n\t\tif ( b && ( !eventType || b[ eventType ] ) ) {\n\t\t\treturn element;\n\t\t}\n\t\telement = element.parentNode;\n\t}\n\treturn null;\n}\n\nfunction enableTouchBindings() {\n\tblockTouchTriggers = false;\n}\n\nfunction disableTouchBindings() {\n\tblockTouchTriggers = true;\n}\n\nfunction enableMouseBindings() {\n\tlastTouchID = 0;\n\tclickBlockList.length = 0;\n\tblockMouseTriggers = false;\n\n\t// When mouse bindings are enabled, our\n\t// touch bindings are disabled.\n\tdisableTouchBindings();\n}\n\nfunction disableMouseBindings() {\n\t// When mouse bindings are disabled, our\n\t// touch bindings are enabled.\n\tenableTouchBindings();\n}\n\nfunction startResetTimer() {\n\tclearResetTimer();\n\tresetTimerID = setTimeout( function() {\n\t\tresetTimerID = 0;\n\t\tenableMouseBindings();\n\t}, $.vmouse.resetTimerDuration );\n}\n\nfunction clearResetTimer() {\n\tif ( resetTimerID ) {\n\t\tclearTimeout( resetTimerID );\n\t\tresetTimerID = 0;\n\t}\n}\n\nfunction triggerVirtualEvent( eventType, event, flags ) {\n\tvar ve;\n\n\tif ( ( flags && flags[ eventType ] ) ||\n\t\t\t\t( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {\n\n\t\tve = createVirtualEvent( event, eventType );\n\n\t\t$( event.target).trigger( ve );\n\t}\n\n\treturn ve;\n}\n\nfunction mouseEventCallback( event ) {\n\tvar touchID = $.data( event.target, touchTargetPropertyName ),\n\t\tve;\n\n\tif ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {\n\t\tve = triggerVirtualEvent( \"v\" + event.type, event );\n\t\tif ( ve ) {\n\t\t\tif ( ve.isDefaultPrevented() ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t\tif ( ve.isPropagationStopped() ) {\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t\tif ( ve.isImmediatePropagationStopped() ) {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction handleTouchStart( event ) {\n\n\tvar touches = getNativeEvent( event ).touches,\n\t\ttarget, flags, t;\n\n\tif ( touches && touches.length === 1 ) {\n\n\t\ttarget = event.target;\n\t\tflags = getVirtualBindingFlags( target );\n\n\t\tif ( flags.hasVirtualBinding ) {\n\n\t\t\tlastTouchID = nextTouchID++;\n\t\t\t$.data( target, touchTargetPropertyName, lastTouchID );\n\n\t\t\tclearResetTimer();\n\n\t\t\tdisableMouseBindings();\n\t\t\tdidScroll = false;\n\n\t\t\tt = getNativeEvent( event ).touches[ 0 ];\n\t\t\tstartX = t.pageX;\n\t\t\tstartY = t.pageY;\n\n\t\t\ttriggerVirtualEvent( \"vmouseover\", event, flags );\n\t\t\ttriggerVirtualEvent( \"vmousedown\", event, flags );\n\t\t}\n\t}\n}\n\nfunction handleScroll( event ) {\n\tif ( blockTouchTriggers ) {\n\t\treturn;\n\t}\n\n\tif ( !didScroll ) {\n\t\ttriggerVirtualEvent( \"vmousecancel\", event, getVirtualBindingFlags( event.target ) );\n\t}\n\n\tdidScroll = true;\n\tstartResetTimer();\n}\n\nfunction handleTouchMove( event ) {\n\tif ( blockTouchTriggers ) {\n\t\treturn;\n\t}\n\n\tvar t = getNativeEvent( event ).touches[ 0 ],\n\t\tdidCancel = didScroll,\n\t\tmoveThreshold = $.vmouse.moveDistanceThreshold,\n\t\tflags = getVirtualBindingFlags( event.target );\n\n\t\tdidScroll = didScroll ||\n\t\t\t( Math.abs( t.pageX - startX ) > moveThreshold ||\n\t\t\t\tMath.abs( t.pageY - startY ) > moveThreshold );\n\n\tif ( didScroll && !didCancel ) {\n\t\ttriggerVirtualEvent( \"vmousecancel\", event, flags );\n\t}\n\n\ttriggerVirtualEvent( \"vmousemove\", event, flags );\n\tstartResetTimer();\n}\n\nfunction handleTouchEnd( event ) {\n\tif ( blockTouchTriggers ) {\n\t\treturn;\n\t}\n\n\tdisableTouchBindings();\n\n\tvar flags = getVirtualBindingFlags( event.target ),\n\t\tve, t;\n\ttriggerVirtualEvent( \"vmouseup\", event, flags );\n\n\tif ( !didScroll ) {\n\t\tve = triggerVirtualEvent( \"vclick\", event, flags );\n\t\tif ( ve && ve.isDefaultPrevented() ) {\n\t\t\t// The target of the mouse events that follow the touchend\n\t\t\t// event don't necessarily match the target used during the\n\t\t\t// touch. This means we need to rely on coordinates for blocking\n\t\t\t// any click that is generated.\n\t\t\tt = getNativeEvent( event ).changedTouches[ 0 ];\n\t\t\tclickBlockList.push({\n\t\t\t\ttouchID: lastTouchID,\n\t\t\t\tx: t.clientX,\n\t\t\t\ty: t.clientY\n\t\t\t});\n\n\t\t\t// Prevent any mouse events that follow from triggering\n\t\t\t// virtual event notifications.\n\t\t\tblockMouseTriggers = true;\n\t\t}\n\t}\n\ttriggerVirtualEvent( \"vmouseout\", event, flags);\n\tdidScroll = false;\n\n\tstartResetTimer();\n}\n\nfunction hasVirtualBindings( ele ) {\n\tvar bindings = $.data( ele, dataPropertyName ),\n\t\tk;\n\n\tif ( bindings ) {\n\t\tfor ( k in bindings ) {\n\t\t\tif ( bindings[ k ] ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction dummyMouseHandler() {}\n\nfunction getSpecialEventObject( eventType ) {\n\tvar realType = eventType.substr( 1 );\n\n\treturn {\n\t\tsetup: function(/* data, namespace */) {\n\t\t\t// If this is the first virtual mouse binding for this element,\n\t\t\t// add a bindings object to its data.\n\n\t\t\tif ( !hasVirtualBindings( this ) ) {\n\t\t\t\t$.data( this, dataPropertyName, {} );\n\t\t\t}\n\n\t\t\t// If setup is called, we know it is the first binding for this\n\t\t\t// eventType, so initialize the count for the eventType to zero.\n\t\t\tvar bindings = $.data( this, dataPropertyName );\n\t\t\tbindings[ eventType ] = true;\n\n\t\t\t// If this is the first virtual mouse event for this type,\n\t\t\t// register a global handler on the document.\n\n\t\t\tactiveDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;\n\n\t\t\tif ( activeDocHandlers[ eventType ] === 1 ) {\n\t\t\t\t$document.bind( realType, mouseEventCallback );\n\t\t\t}\n\n\t\t\t// Some browsers, like Opera Mini, won't dispatch mouse/click events\n\t\t\t// for elements unless they actually have handlers registered on them.\n\t\t\t// To get around this, we register dummy handlers on the elements.\n\n\t\t\t$( this ).bind( realType, dummyMouseHandler );\n\n\t\t\t// For now, if event capture is not supported, we rely on mouse handlers.\n\t\t\tif ( eventCaptureSupported ) {\n\t\t\t\t// If this is the first virtual mouse binding for the document,\n\t\t\t\t// register our touchstart handler on the document.\n\n\t\t\t\tactiveDocHandlers[ \"touchstart\" ] = ( activeDocHandlers[ \"touchstart\" ] || 0) + 1;\n\n\t\t\t\tif ( activeDocHandlers[ \"touchstart\" ] === 1 ) {\n\t\t\t\t\t$document.bind( \"touchstart\", handleTouchStart )\n\t\t\t\t\t\t.bind( \"touchend\", handleTouchEnd )\n\n\t\t\t\t\t\t// On touch platforms, touching the screen and then dragging your finger\n\t\t\t\t\t\t// causes the window content to scroll after some distance threshold is\n\t\t\t\t\t\t// exceeded. On these platforms, a scroll prevents a click event from being\n\t\t\t\t\t\t// dispatched, and on some platforms, even the touchend is suppressed. To\n\t\t\t\t\t\t// mimic the suppression of the click event, we need to watch for a scroll\n\t\t\t\t\t\t// event. Unfortunately, some platforms like iOS don't dispatch scroll\n\t\t\t\t\t\t// events until *AFTER* the user lifts their finger (touchend). This means\n\t\t\t\t\t\t// we need to watch both scroll and touchmove events to figure out whether\n\t\t\t\t\t\t// or not a scroll happenens before the touchend event is fired.\n\n\t\t\t\t\t\t.bind( \"touchmove\", handleTouchMove )\n\t\t\t\t\t\t.bind( \"scroll\", handleScroll );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function(/* data, namespace */) {\n\t\t\t// If this is the last virtual binding for this eventType,\n\t\t\t// remove its global handler from the document.\n\n\t\t\t--activeDocHandlers[ eventType ];\n\n\t\t\tif ( !activeDocHandlers[ eventType ] ) {\n\t\t\t\t$document.unbind( realType, mouseEventCallback );\n\t\t\t}\n\n\t\t\tif ( eventCaptureSupported ) {\n\t\t\t\t// If this is the last virtual mouse binding in existence,\n\t\t\t\t// remove our document touchstart listener.\n\n\t\t\t\t--activeDocHandlers[ \"touchstart\" ];\n\n\t\t\t\tif ( !activeDocHandlers[ \"touchstart\" ] ) {\n\t\t\t\t\t$document.unbind( \"touchstart\", handleTouchStart )\n\t\t\t\t\t\t.unbind( \"touchmove\", handleTouchMove )\n\t\t\t\t\t\t.unbind( \"touchend\", handleTouchEnd )\n\t\t\t\t\t\t.unbind( \"scroll\", handleScroll );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar $this = $( this ),\n\t\t\t\tbindings = $.data( this, dataPropertyName );\n\n\t\t\t// teardown may be called when an element was\n\t\t\t// removed from the DOM. If this is the case,\n\t\t\t// jQuery core may have already stripped the element\n\t\t\t// of any data bindings so we need to check it before\n\t\t\t// using it.\n\t\t\tif ( bindings ) {\n\t\t\t\tbindings[ eventType ] = false;\n\t\t\t}\n\n\t\t\t// Unregister the dummy event handler.\n\n\t\t\t$this.unbind( realType, dummyMouseHandler );\n\n\t\t\t// If this is the last virtual mouse binding on the\n\t\t\t// element, remove the binding data from the element.\n\n\t\t\tif ( !hasVirtualBindings( this ) ) {\n\t\t\t\t$this.removeData( dataPropertyName );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Expose our custom events to the jQuery bind/unbind mechanism.\n\nfor ( i = 0; i < virtualEventNames.length; i++ ) {\n\t$.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );\n}\n\n// Add a capture click handler to block clicks.\n// Note that we require event capture support for this so if the device\n// doesn't support it, we punt for now and rely solely on mouse events.\nif ( eventCaptureSupported ) {\n\tdocument.addEventListener( \"click\", function( e ) {\n\t\tvar cnt = clickBlockList.length,\n\t\t\ttarget = e.target,\n\t\t\tx, y, ele, i, o, touchID;\n\n\t\tif ( cnt ) {\n\t\t\tx = e.clientX;\n\t\t\ty = e.clientY;\n\t\t\tthreshold = $.vmouse.clickDistanceThreshold;\n\n\t\t\t// The idea here is to run through the clickBlockList to see if\n\t\t\t// the current click event is in the proximity of one of our\n\t\t\t// vclick events that had preventDefault() called on it. If we find\n\t\t\t// one, then we block the click.\n\t\t\t//\n\t\t\t// Why do we have to rely on proximity?\n\t\t\t//\n\t\t\t// Because the target of the touch event that triggered the vclick\n\t\t\t// can be different from the target of the click event synthesized\n\t\t\t// by the browser. The target of a mouse/click event that is synthesized\n\t\t\t// from a touch event seems to be implementation specific. For example,\n\t\t\t// some browsers will fire mouse/click events for a link that is near\n\t\t\t// a touch event, even though the target of the touchstart/touchend event\n\t\t\t// says the user touched outside the link. Also, it seems that with most\n\t\t\t// browsers, the target of the mouse/click event is not calculated until the\n\t\t\t// time it is dispatched, so if you replace an element that you touched\n\t\t\t// with another element, the target of the mouse/click will be the new\n\t\t\t// element underneath that point.\n\t\t\t//\n\t\t\t// Aside from proximity, we also check to see if the target and any\n\t\t\t// of its ancestors were the ones that blocked a click. This is necessary\n\t\t\t// because of the strange mouse/click target calculation done in the\n\t\t\t// Android 2.1 browser, where if you click on an element, and there is a\n\t\t\t// mouse/click handler on one of its ancestors, the target will be the\n\t\t\t// innermost child of the touched element, even if that child is no where\n\t\t\t// near the point of touch.\n\n\t\t\tele = target;\n\n\t\t\twhile ( ele ) {\n\t\t\t\tfor ( i = 0; i < cnt; i++ ) {\n\t\t\t\t\to = clickBlockList[ i ];\n\t\t\t\t\ttouchID = 0;\n\n\t\t\t\t\tif ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||\n\t\t\t\t\t\t\t\t$.data( ele, touchTargetPropertyName ) === o.touchID ) {\n\t\t\t\t\t\t// XXX: We may want to consider removing matches from the block list\n\t\t\t\t\t\t//      instead of waiting for the reset timer to fire.\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tele = ele.parentNode;\n\t\t\t}\n\t\t}\n\t}, true);\n}\n})( jQuery, window, document );\n\n\n(function( $, window, undefined ) {\n\tvar $document = $( document ),\n\t\tsupportTouch = $.mobile.support.touch,\n\t\tscrollEvent = \"touchmove scroll\",\n\t\ttouchStartEvent = supportTouch ? \"touchstart\" : \"mousedown\",\n\t\ttouchStopEvent = supportTouch ? \"touchend\" : \"mouseup\",\n\t\ttouchMoveEvent = supportTouch ? \"touchmove\" : \"mousemove\";\n\n\t// setup new event shortcuts\n\t$.each( ( \"touchstart touchmove touchend \" +\n\t\t\"tap taphold \" +\n\t\t\"swipe swipeleft swiperight \" +\n\t\t\"scrollstart scrollstop\" ).split( \" \" ), function( i, name ) {\n\n\t\t$.fn[ name ] = function( fn ) {\n\t\t\treturn fn ? this.bind( name, fn ) : this.trigger( name );\n\t\t};\n\n\t\t// jQuery < 1.8\n\t\tif ( $.attrFn ) {\n\t\t\t$.attrFn[ name ] = true;\n\t\t}\n\t});\n\n\tfunction triggerCustomEvent( obj, eventType, event, bubble ) {\n\t\tvar originalType = event.type;\n\t\tevent.type = eventType;\n\t\tif ( bubble ) {\n\t\t\t$.event.trigger( event, undefined, obj );\n\t\t} else {\n\t\t\t$.event.dispatch.call( obj, event );\n\t\t}\n\t\tevent.type = originalType;\n\t}\n\n\t// also handles scrollstop\n\t$.event.special.scrollstart = {\n\n\t\tenabled: true,\n\t\tsetup: function() {\n\n\t\t\tvar thisObject = this,\n\t\t\t\t$this = $( thisObject ),\n\t\t\t\tscrolling,\n\t\t\t\ttimer;\n\n\t\t\tfunction trigger( event, state ) {\n\t\t\t\tscrolling = state;\n\t\t\t\ttriggerCustomEvent( thisObject, scrolling ? \"scrollstart\" : \"scrollstop\", event );\n\t\t\t}\n\n\t\t\t// iPhone triggers scroll after a small delay; use touchmove instead\n\t\t\t$this.bind( scrollEvent, function( event ) {\n\n\t\t\t\tif ( !$.event.special.scrollstart.enabled ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( !scrolling ) {\n\t\t\t\t\ttrigger( event, true );\n\t\t\t\t}\n\n\t\t\t\tclearTimeout( timer );\n\t\t\t\ttimer = setTimeout( function() {\n\t\t\t\t\ttrigger( event, false );\n\t\t\t\t}, 50 );\n\t\t\t});\n\t\t},\n\t\tteardown: function() {\n\t\t\t$( this ).unbind( scrollEvent );\n\t\t}\n\t};\n\n\t// also handles taphold\n\t$.event.special.tap = {\n\t\ttapholdThreshold: 750,\n\t\temitTapOnTaphold: true,\n\t\tsetup: function() {\n\t\t\tvar thisObject = this,\n\t\t\t\t$this = $( thisObject ),\n\t\t\t\tisTaphold = false;\n\n\t\t\t$this.bind( \"vmousedown\", function( event ) {\n\t\t\t\tisTaphold = false;\n\t\t\t\tif ( event.which && event.which !== 1 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tvar origTarget = event.target,\n\t\t\t\t\ttimer;\n\n\t\t\t\tfunction clearTapTimer() {\n\t\t\t\t\tclearTimeout( timer );\n\t\t\t\t}\n\n\t\t\t\tfunction clearTapHandlers() {\n\t\t\t\t\tclearTapTimer();\n\n\t\t\t\t\t$this.unbind( \"vclick\", clickHandler )\n\t\t\t\t\t\t.unbind( \"vmouseup\", clearTapTimer );\n\t\t\t\t\t$document.unbind( \"vmousecancel\", clearTapHandlers );\n\t\t\t\t}\n\n\t\t\t\tfunction clickHandler( event ) {\n\t\t\t\t\tclearTapHandlers();\n\n\t\t\t\t\t// ONLY trigger a 'tap' event if the start target is\n\t\t\t\t\t// the same as the stop target.\n\t\t\t\t\tif ( !isTaphold && origTarget === event.target ) {\n\t\t\t\t\t\ttriggerCustomEvent( thisObject, \"tap\", event );\n\t\t\t\t\t} else if ( isTaphold ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$this.bind( \"vmouseup\", clearTapTimer )\n\t\t\t\t\t.bind( \"vclick\", clickHandler );\n\t\t\t\t$document.bind( \"vmousecancel\", clearTapHandlers );\n\n\t\t\t\ttimer = setTimeout( function() {\n\t\t\t\t\tif ( !$.event.special.tap.emitTapOnTaphold ) {\n\t\t\t\t\t\tisTaphold = true;\n\t\t\t\t\t}\n\t\t\t\t\ttriggerCustomEvent( thisObject, \"taphold\", $.Event( \"taphold\", { target: origTarget } ) );\n\t\t\t\t}, $.event.special.tap.tapholdThreshold );\n\t\t\t});\n\t\t},\n\t\tteardown: function() {\n\t\t\t$( this ).unbind( \"vmousedown\" ).unbind( \"vclick\" ).unbind( \"vmouseup\" );\n\t\t\t$document.unbind( \"vmousecancel\" );\n\t\t}\n\t};\n\n\t// Also handles swipeleft, swiperight\n\t$.event.special.swipe = {\n\n\t\t// More than this horizontal displacement, and we will suppress scrolling.\n\t\tscrollSupressionThreshold: 30,\n\n\t\t// More time than this, and it isn't a swipe.\n\t\tdurationThreshold: 1000,\n\n\t\t// Swipe horizontal displacement must be more than this.\n\t\thorizontalDistanceThreshold: 30,\n\n\t\t// Swipe vertical displacement must be less than this.\n\t\tverticalDistanceThreshold: 30,\n\n\t\tgetLocation: function ( event ) {\n\t\t\tvar winPageX = window.pageXOffset,\n\t\t\t\twinPageY = window.pageYOffset,\n\t\t\t\tx = event.clientX,\n\t\t\t\ty = event.clientY;\n\n\t\t\tif ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) ||\n\t\t\t\tevent.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) {\n\n\t\t\t\t// iOS4 clientX/clientY have the value that should have been\n\t\t\t\t// in pageX/pageY. While pageX/page/ have the value 0\n\t\t\t\tx = x - winPageX;\n\t\t\t\ty = y - winPageY;\n\t\t\t} else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) {\n\n\t\t\t\t// Some Android browsers have totally bogus values for clientX/Y\n\t\t\t\t// when scrolling/zooming a page. Detectable since clientX/clientY\n\t\t\t\t// should never be smaller than pageX/pageY minus page scroll\n\t\t\t\tx = event.pageX - winPageX;\n\t\t\t\ty = event.pageY - winPageY;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tx: x,\n\t\t\t\ty: y\n\t\t\t};\n\t\t},\n\n\t\tstart: function( event ) {\n\t\t\tvar data = event.originalEvent.touches ?\n\t\t\t\t\tevent.originalEvent.touches[ 0 ] : event,\n\t\t\t\tlocation = $.event.special.swipe.getLocation( data );\n\t\t\treturn {\n\t\t\t\t\t\ttime: ( new Date() ).getTime(),\n\t\t\t\t\t\tcoords: [ location.x, location.y ],\n\t\t\t\t\t\torigin: $( event.target )\n\t\t\t\t\t};\n\t\t},\n\n\t\tstop: function( event ) {\n\t\t\tvar data = event.originalEvent.touches ?\n\t\t\t\t\tevent.originalEvent.touches[ 0 ] : event,\n\t\t\t\tlocation = $.event.special.swipe.getLocation( data );\n\t\t\treturn {\n\t\t\t\t\t\ttime: ( new Date() ).getTime(),\n\t\t\t\t\t\tcoords: [ location.x, location.y ]\n\t\t\t\t\t};\n\t\t},\n\n\t\thandleSwipe: function( start, stop, thisObject, origTarget ) {\n\t\t\tif ( stop.time - start.time < $.event.special.swipe.durationThreshold &&\n\t\t\t\tMath.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&\n\t\t\t\tMath.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {\n\t\t\t\tvar direction = start.coords[0] > stop.coords[ 0 ] ? \"swipeleft\" : \"swiperight\";\n\n\t\t\t\ttriggerCustomEvent( thisObject, \"swipe\", $.Event( \"swipe\", { target: origTarget, swipestart: start, swipestop: stop }), true );\n\t\t\t\ttriggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true );\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\n\t\t},\n\n\t\t// This serves as a flag to ensure that at most one swipe event event is\n\t\t// in work at any given time\n\t\teventInProgress: false,\n\n\t\tsetup: function() {\n\t\t\tvar events,\n\t\t\t\tthisObject = this,\n\t\t\t\t$this = $( thisObject ),\n\t\t\t\tcontext = {};\n\n\t\t\t// Retrieve the events data for this element and add the swipe context\n\t\t\tevents = $.data( this, \"mobile-events\" );\n\t\t\tif ( !events ) {\n\t\t\t\tevents = { length: 0 };\n\t\t\t\t$.data( this, \"mobile-events\", events );\n\t\t\t}\n\t\t\tevents.length++;\n\t\t\tevents.swipe = context;\n\n\t\t\tcontext.start = function( event ) {\n\n\t\t\t\t// Bail if we're already working on a swipe event\n\t\t\t\tif ( $.event.special.swipe.eventInProgress ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t$.event.special.swipe.eventInProgress = true;\n\n\t\t\t\tvar stop,\n\t\t\t\t\tstart = $.event.special.swipe.start( event ),\n\t\t\t\t\torigTarget = event.target,\n\t\t\t\t\temitted = false;\n\n\t\t\t\tcontext.move = function( event ) {\n\t\t\t\t\tif ( !start || event.isDefaultPrevented() ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tstop = $.event.special.swipe.stop( event );\n\t\t\t\t\tif ( !emitted ) {\n\t\t\t\t\t\temitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget );\n\t\t\t\t\t\tif ( emitted ) {\n\n\t\t\t\t\t\t\t// Reset the context to make way for the next swipe event\n\t\t\t\t\t\t\t$.event.special.swipe.eventInProgress = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// prevent scrolling\n\t\t\t\t\tif ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tcontext.stop = function() {\n\t\t\t\t\t\temitted = true;\n\n\t\t\t\t\t\t// Reset the context to make way for the next swipe event\n\t\t\t\t\t\t$.event.special.swipe.eventInProgress = false;\n\t\t\t\t\t\t$document.off( touchMoveEvent, context.move );\n\t\t\t\t\t\tcontext.move = null;\n\t\t\t\t};\n\n\t\t\t\t$document.on( touchMoveEvent, context.move )\n\t\t\t\t\t.one( touchStopEvent, context.stop );\n\t\t\t};\n\t\t\t$this.on( touchStartEvent, context.start );\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tvar events, context;\n\n\t\t\tevents = $.data( this, \"mobile-events\" );\n\t\t\tif ( events ) {\n\t\t\t\tcontext = events.swipe;\n\t\t\t\tdelete events.swipe;\n\t\t\t\tevents.length--;\n\t\t\t\tif ( events.length === 0 ) {\n\t\t\t\t\t$.removeData( this, \"mobile-events\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( context ) {\n\t\t\t\tif ( context.start ) {\n\t\t\t\t\t$( this ).off( touchStartEvent, context.start );\n\t\t\t\t}\n\t\t\t\tif ( context.move ) {\n\t\t\t\t\t$document.off( touchMoveEvent, context.move );\n\t\t\t\t}\n\t\t\t\tif ( context.stop ) {\n\t\t\t\t\t$document.off( touchStopEvent, context.stop );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\t$.each({\n\t\tscrollstop: \"scrollstart\",\n\t\ttaphold: \"tap\",\n\t\tswipeleft: \"swipe.left\",\n\t\tswiperight: \"swipe.right\"\n\t}, function( event, sourceEvent ) {\n\n\t\t$.event.special[ event ] = {\n\t\t\tsetup: function() {\n\t\t\t\t$( this ).bind( sourceEvent, $.noop );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\t$( this ).unbind( sourceEvent );\n\t\t\t}\n\t\t};\n\t});\n\n})( jQuery, this );\n\n\n\t// throttled resize event\n\t(function( $ ) {\n\t\t$.event.special.throttledresize = {\n\t\t\tsetup: function() {\n\t\t\t\t$( this ).bind( \"resize\", handler );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\t$( this ).unbind( \"resize\", handler );\n\t\t\t}\n\t\t};\n\n\t\tvar throttle = 250,\n\t\t\thandler = function() {\n\t\t\t\tcurr = ( new Date() ).getTime();\n\t\t\t\tdiff = curr - lastCall;\n\n\t\t\t\tif ( diff >= throttle ) {\n\n\t\t\t\t\tlastCall = curr;\n\t\t\t\t\t$( this ).trigger( \"throttledresize\" );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( heldCall ) {\n\t\t\t\t\t\tclearTimeout( heldCall );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Promise a held call will still execute\n\t\t\t\t\theldCall = setTimeout( handler, throttle - diff );\n\t\t\t\t}\n\t\t\t},\n\t\t\tlastCall = 0,\n\t\t\theldCall,\n\t\t\tcurr,\n\t\t\tdiff;\n\t})( jQuery );\n\n\n(function( $, window ) {\n\tvar win = $( window ),\n\t\tevent_name = \"orientationchange\",\n\t\tget_orientation,\n\t\tlast_orientation,\n\t\tinitial_orientation_is_landscape,\n\t\tinitial_orientation_is_default,\n\t\tportrait_map = { \"0\": true, \"180\": true },\n\t\tww, wh, landscape_threshold;\n\n\t// It seems that some device/browser vendors use window.orientation values 0 and 180 to\n\t// denote the \"default\" orientation. For iOS devices, and most other smart-phones tested,\n\t// the default orientation is always \"portrait\", but in some Android and RIM based tablets,\n\t// the default orientation is \"landscape\". The following code attempts to use the window\n\t// dimensions to figure out what the current orientation is, and then makes adjustments\n\t// to the to the portrait_map if necessary, so that we can properly decode the\n\t// window.orientation value whenever get_orientation() is called.\n\t//\n\t// Note that we used to use a media query to figure out what the orientation the browser\n\t// thinks it is in:\n\t//\n\t//     initial_orientation_is_landscape = $.mobile.media(\"all and (orientation: landscape)\");\n\t//\n\t// but there was an iPhone/iPod Touch bug beginning with iOS 4.2, up through iOS 5.1,\n\t// where the browser *ALWAYS* applied the landscape media query. This bug does not\n\t// happen on iPad.\n\n\tif ( $.support.orientation ) {\n\n\t\t// Check the window width and height to figure out what the current orientation\n\t\t// of the device is at this moment. Note that we've initialized the portrait map\n\t\t// values to 0 and 180, *AND* we purposely check for landscape so that if we guess\n\t\t// wrong, , we default to the assumption that portrait is the default orientation.\n\t\t// We use a threshold check below because on some platforms like iOS, the iPhone\n\t\t// form-factor can report a larger width than height if the user turns on the\n\t\t// developer console. The actual threshold value is somewhat arbitrary, we just\n\t\t// need to make sure it is large enough to exclude the developer console case.\n\n\t\tww = window.innerWidth || win.width();\n\t\twh = window.innerHeight || win.height();\n\t\tlandscape_threshold = 50;\n\n\t\tinitial_orientation_is_landscape = ww > wh && ( ww - wh ) > landscape_threshold;\n\n\t\t// Now check to see if the current window.orientation is 0 or 180.\n\t\tinitial_orientation_is_default = portrait_map[ window.orientation ];\n\n\t\t// If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR*\n\t\t// if the initial orientation is portrait, but window.orientation reports 90 or -90, we\n\t\t// need to flip our portrait_map values because landscape is the default orientation for\n\t\t// this device/browser.\n\t\tif ( ( initial_orientation_is_landscape && initial_orientation_is_default ) || ( !initial_orientation_is_landscape && !initial_orientation_is_default ) ) {\n\t\t\tportrait_map = { \"-90\": true, \"90\": true };\n\t\t}\n\t}\n\n\t$.event.special.orientationchange = $.extend( {}, $.event.special.orientationchange, {\n\t\tsetup: function() {\n\t\t\t// If the event is supported natively, return false so that jQuery\n\t\t\t// will bind to the event using DOM methods.\n\t\t\tif ( $.support.orientation && !$.event.special.orientationchange.disabled ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Get the current orientation to avoid initial double-triggering.\n\t\t\tlast_orientation = get_orientation();\n\n\t\t\t// Because the orientationchange event doesn't exist, simulate the\n\t\t\t// event by testing window dimensions on resize.\n\t\t\twin.bind( \"throttledresize\", handler );\n\t\t},\n\t\tteardown: function() {\n\t\t\t// If the event is not supported natively, return false so that\n\t\t\t// jQuery will unbind the event using DOM methods.\n\t\t\tif ( $.support.orientation && !$.event.special.orientationchange.disabled ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Because the orientationchange event doesn't exist, unbind the\n\t\t\t// resize event handler.\n\t\t\twin.unbind( \"throttledresize\", handler );\n\t\t},\n\t\tadd: function( handleObj ) {\n\t\t\t// Save a reference to the bound event handler.\n\t\t\tvar old_handler = handleObj.handler;\n\n\t\t\thandleObj.handler = function( event ) {\n\t\t\t\t// Modify event object, adding the .orientation property.\n\t\t\t\tevent.orientation = get_orientation();\n\n\t\t\t\t// Call the originally-bound event handler and return its result.\n\t\t\t\treturn old_handler.apply( this, arguments );\n\t\t\t};\n\t\t}\n\t});\n\n\t// If the event is not supported natively, this handler will be bound to\n\t// the window resize event to simulate the orientationchange event.\n\tfunction handler() {\n\t\t// Get the current orientation.\n\t\tvar orientation = get_orientation();\n\n\t\tif ( orientation !== last_orientation ) {\n\t\t\t// The orientation has changed, so trigger the orientationchange event.\n\t\t\tlast_orientation = orientation;\n\t\t\twin.trigger( event_name );\n\t\t}\n\t}\n\n\t// Get the current page orientation. This method is exposed publicly, should it\n\t// be needed, as jQuery.event.special.orientationchange.orientation()\n\t$.event.special.orientationchange.orientation = get_orientation = function() {\n\t\tvar isPortrait = true, elem = document.documentElement;\n\n\t\t// prefer window orientation to the calculation based on screensize as\n\t\t// the actual screen resize takes place before or after the orientation change event\n\t\t// has been fired depending on implementation (eg android 2.3 is before, iphone after).\n\t\t// More testing is required to determine if a more reliable method of determining the new screensize\n\t\t// is possible when orientationchange is fired. (eg, use media queries + element + opacity)\n\t\tif ( $.support.orientation ) {\n\t\t\t// if the window orientation registers as 0 or 180 degrees report\n\t\t\t// portrait, otherwise landscape\n\t\t\tisPortrait = portrait_map[ window.orientation ];\n\t\t} else {\n\t\t\tisPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;\n\t\t}\n\n\t\treturn isPortrait ? \"portrait\" : \"landscape\";\n\t};\n\n\t$.fn[ event_name ] = function( fn ) {\n\t\treturn fn ? this.bind( event_name, fn ) : this.trigger( event_name );\n\t};\n\n\t// jQuery < 1.8\n\tif ( $.attrFn ) {\n\t\t$.attrFn[ event_name ] = true;\n\t}\n\n}( jQuery, this ));\n\n\n\n\n(function( $, undefined ) {\n\n\t// existing base tag?\n\tvar baseElement = $( \"head\" ).children( \"base\" ),\n\n\t// base element management, defined depending on dynamic base tag support\n\t// TODO move to external widget\n\tbase = {\n\n\t\t// define base element, for use in routing asset urls that are referenced\n\t\t// in Ajax-requested markup\n\t\telement: ( baseElement.length ? baseElement :\n\t\t\t$( \"<base>\", { href: $.mobile.path.documentBase.hrefNoHash } ).prependTo( $( \"head\" ) ) ),\n\n\t\tlinkSelector: \"[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]\",\n\n\t\t// set the generated BASE element's href to a new page's base path\n\t\tset: function( href ) {\n\n\t\t\t// we should do nothing if the user wants to manage their url base\n\t\t\t// manually\n\t\t\tif ( !$.mobile.dynamicBaseEnabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// we should use the base tag if we can manipulate it dynamically\n\t\t\tif ( $.support.dynamicBaseTag ) {\n\t\t\t\tbase.element.attr( \"href\",\n\t\t\t\t\t$.mobile.path.makeUrlAbsolute( href, $.mobile.path.documentBase ) );\n\t\t\t}\n\t\t},\n\n\t\trewrite: function( href, page ) {\n\t\t\tvar newPath = $.mobile.path.get( href );\n\n\t\t\tpage.find( base.linkSelector ).each(function( i, link ) {\n\t\t\t\tvar thisAttr = $( link ).is( \"[href]\" ) ? \"href\" :\n\t\t\t\t\t$( link ).is( \"[src]\" ) ? \"src\" : \"action\",\n\t\t\t\ttheLocation = $.mobile.path.parseLocation(),\n\t\t\t\tthisUrl = $( link ).attr( thisAttr );\n\n\t\t\t\t// XXX_jblas: We need to fix this so that it removes the document\n\t\t\t\t//            base URL, and then prepends with the new page URL.\n\t\t\t\t// if full path exists and is same, chop it - helps IE out\n\t\t\t\tthisUrl = thisUrl.replace( theLocation.protocol + theLocation.doubleSlash +\n\t\t\t\t\ttheLocation.host + theLocation.pathname, \"\" );\n\n\t\t\t\tif ( !/^(\\w+:|#|\\/)/.test( thisUrl ) ) {\n\t\t\t\t\t$( link ).attr( thisAttr, newPath + thisUrl );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\t// set the generated BASE element's href to a new page's base path\n\t\treset: function(/* href */) {\n\t\t\tbase.element.attr( \"href\", $.mobile.path.documentBase.hrefNoSearch );\n\t\t}\n\t};\n\n\t$.mobile.base = base;\n\n})( jQuery );\n\n\n(function( $, undefined ) {\n$.mobile.widgets = {};\n\nvar originalWidget = $.widget,\n\n\t// Record the original, non-mobileinit-modified version of $.mobile.keepNative\n\t// so we can later determine whether someone has modified $.mobile.keepNative\n\tkeepNativeFactoryDefault = $.mobile.keepNative;\n\n$.widget = (function( orig ) {\n\treturn function() {\n\t\tvar constructor = orig.apply( this, arguments ),\n\t\t\tname = constructor.prototype.widgetName;\n\n\t\tconstructor.initSelector = ( ( constructor.prototype.initSelector !== undefined ) ?\n\t\t\tconstructor.prototype.initSelector : \":jqmData(role='\" + name + \"')\" );\n\n\t\t$.mobile.widgets[ name ] = constructor;\n\n\t\treturn constructor;\n\t};\n})( $.widget );\n\n// Make sure $.widget still has bridge and extend methods\n$.extend( $.widget, originalWidget );\n\n// For backcompat remove in 1.5\n$.mobile.document.on( \"create\", function( event ) {\n\t$( event.target ).enhanceWithin();\n});\n\n$.widget( \"mobile.page\", {\n\toptions: {\n\t\ttheme: \"a\",\n\t\tdomCache: false,\n\n\t\t// Deprecated in 1.4 remove in 1.5\n\t\tkeepNativeDefault: $.mobile.keepNative,\n\n\t\t// Deprecated in 1.4 remove in 1.5\n\t\tcontentTheme: null,\n\t\tenhanced: false\n\t},\n\n\t// DEPRECATED for > 1.4\n\t// TODO remove at 1.5\n\t_createWidget: function() {\n\t\t$.Widget.prototype._createWidget.apply( this, arguments );\n\t\tthis._trigger( \"init\" );\n\t},\n\n\t_create: function() {\n\t\t// If false is returned by the callbacks do not create the page\n\t\tif ( this._trigger( \"beforecreate\" ) === false ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !this.options.enhanced ) {\n\t\t\tthis._enhance();\n\t\t}\n\n\t\tthis._on( this.element, {\n\t\t\tpagebeforehide: \"removeContainerBackground\",\n\t\t\tpagebeforeshow: \"_handlePageBeforeShow\"\n\t\t});\n\n\t\tthis.element.enhanceWithin();\n\t\t// Dialog widget is deprecated in 1.4 remove this in 1.5\n\t\tif ( $.mobile.getAttribute( this.element[0], \"role\" ) === \"dialog\" && $.mobile.dialog ) {\n\t\t\tthis.element.dialog();\n\t\t}\n\t},\n\n\t_enhance: function () {\n\t\tvar attrPrefix = \"data-\" + $.mobile.ns,\n\t\t\tself = this;\n\n\t\tif ( this.options.role ) {\n\t\t\tthis.element.attr( \"data-\" + $.mobile.ns + \"role\", this.options.role );\n\t\t}\n\n\t\tthis.element\n\t\t\t.attr( \"tabindex\", \"0\" )\n\t\t\t.addClass( \"ui-page ui-page-theme-\" + this.options.theme );\n\n\t\t// Manipulation of content os Deprecated as of 1.4 remove in 1.5\n\t\tthis.element.find( \"[\" + attrPrefix + \"role='content']\" ).each( function() {\n\t\t\tvar $this = $( this ),\n\t\t\t\ttheme = this.getAttribute( attrPrefix + \"theme\" ) || undefined;\n\t\t\t\tself.options.contentTheme = theme || self.options.contentTheme || ( self.options.dialog && self.options.theme ) || ( self.element.jqmData(\"role\") === \"dialog\" &&  self.options.theme );\n\t\t\t\t$this.addClass( \"ui-content\" );\n\t\t\t\tif ( self.options.contentTheme ) {\n\t\t\t\t\t$this.addClass( \"ui-body-\" + ( self.options.contentTheme ) );\n\t\t\t\t}\n\t\t\t\t// Add ARIA role\n\t\t\t\t$this.attr( \"role\", \"main\" ).addClass( \"ui-content\" );\n\t\t});\n\t},\n\n\tbindRemove: function( callback ) {\n\t\tvar page = this.element;\n\n\t\t// when dom caching is not enabled or the page is embedded bind to remove the page on hide\n\t\tif ( !page.data( \"mobile-page\" ).options.domCache &&\n\t\t\tpage.is( \":jqmData(external-page='true')\" ) ) {\n\n\t\t\t// TODO use _on - that is, sort out why it doesn't work in this case\n\t\t\tpage.bind( \"pagehide.remove\", callback || function( e, data ) {\n\n\t\t\t\t//check if this is a same page transition and if so don't remove the page\n\t\t\t\tif( !data.samePage ){\n\t\t\t\t\tvar $this = $( this ),\n\t\t\t\t\t\tprEvent = new $.Event( \"pageremove\" );\n\n\t\t\t\t\t$this.trigger( prEvent );\n\n\t\t\t\t\tif ( !prEvent.isDefaultPrevented() ) {\n\t\t\t\t\t\t$this.removeWithDependents();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\t_setOptions: function( o ) {\n\t\tif ( o.theme !== undefined ) {\n\t\t\tthis.element.removeClass( \"ui-page-theme-\" + this.options.theme ).addClass( \"ui-page-theme-\" + o.theme );\n\t\t}\n\n\t\tif ( o.contentTheme !== undefined ) {\n\t\t\tthis.element.find( \"[data-\" + $.mobile.ns + \"='content']\" ).removeClass( \"ui-body-\" + this.options.contentTheme )\n\t\t\t\t.addClass( \"ui-body-\" + o.contentTheme );\n\t\t}\n\t},\n\n\t_handlePageBeforeShow: function(/* e */) {\n\t\tthis.setContainerBackground();\n\t},\n\t// Deprecated in 1.4 remove in 1.5\n\tremoveContainerBackground: function() {\n\t\tthis.element.closest( \":mobile-pagecontainer\" ).pagecontainer({ \"theme\": \"none\" });\n\t},\n\t// Deprecated in 1.4 remove in 1.5\n\t// set the page container background to the page theme\n\tsetContainerBackground: function( theme ) {\n\t\tthis.element.parent().pagecontainer( { \"theme\": theme || this.options.theme } );\n\t},\n\t// Deprecated in 1.4 remove in 1.5\n\tkeepNativeSelector: function() {\n\t\tvar options = this.options,\n\t\t\tkeepNative = $.trim( options.keepNative || \"\" ),\n\t\t\tglobalValue = $.trim( $.mobile.keepNative ),\n\t\t\toptionValue = $.trim( options.keepNativeDefault ),\n\n\t\t\t// Check if $.mobile.keepNative has changed from the factory default\n\t\t\tnewDefault = ( keepNativeFactoryDefault === globalValue ?\n\t\t\t\t\"\" : globalValue ),\n\n\t\t\t// If $.mobile.keepNative has not changed, use options.keepNativeDefault\n\t\t\toldDefault = ( newDefault === \"\" ? optionValue : \"\" );\n\n\t\t// Concatenate keepNative selectors from all sources where the value has\n\t\t// changed or, if nothing has changed, return the default\n\t\treturn ( ( keepNative ? [ keepNative ] : [] )\n\t\t\t.concat( newDefault ? [ newDefault ] : [] )\n\t\t\t.concat( oldDefault ? [ oldDefault ] : [] )\n\t\t\t.join( \", \" ) );\n\t}\n});\n})( jQuery );\n\n(function( $, undefined ) {\n\n\t$.widget( \"mobile.pagecontainer\", {\n\t\toptions: {\n\t\t\ttheme: \"a\"\n\t\t},\n\n\t\tinitSelector: false,\n\n\t\t_create: function() {\n\t\t\tthis._trigger( \"beforecreate\" );\n\t\t\tthis.setLastScrollEnabled = true;\n\n\t\t\tthis._on( this.window, {\n\t\t\t\t// disable an scroll setting when a hashchange has been fired,\n\t\t\t\t// this only works because the recording of the scroll position\n\t\t\t\t// is delayed for 100ms after the browser might have changed the\n\t\t\t\t// position because of the hashchange\n\t\t\t\tnavigate: \"_disableRecordScroll\",\n\n\t\t\t\t// bind to scrollstop for the first page, \"pagechange\" won't be\n\t\t\t\t// fired in that case\n\t\t\t\tscrollstop: \"_delayedRecordScroll\"\n\t\t\t});\n\n\t\t\t// TODO consider moving the navigation handler OUT of widget into\n\t\t\t//      some other object as glue between the navigate event and the\n\t\t\t//      content widget load and change methods\n\t\t\tthis._on( this.window, { navigate: \"_filterNavigateEvents\" });\n\n\t\t\t// TODO move from page* events to content* events\n\t\t\tthis._on({ pagechange: \"_afterContentChange\" });\n\n\t\t\t// handle initial hashchange from chrome :(\n\t\t\tthis.window.one( \"navigate\", $.proxy(function() {\n\t\t\t\tthis.setLastScrollEnabled = true;\n\t\t\t}, this));\n\t\t},\n\n\t\t_setOptions: function( options ) {\n\t\t\tif ( options.theme !== undefined && options.theme !== \"none\" ) {\n\t\t\t\tthis.element.removeClass( \"ui-overlay-\" + this.options.theme )\n\t\t\t\t\t.addClass( \"ui-overlay-\" + options.theme );\n\t\t\t} else if ( options.theme !== undefined ) {\n\t\t\t\tthis.element.removeClass( \"ui-overlay-\" + this.options.theme );\n\t\t\t}\n\n\t\t\tthis._super( options );\n\t\t},\n\n\t\t_disableRecordScroll: function() {\n\t\t\tthis.setLastScrollEnabled = false;\n\t\t},\n\n\t\t_enableRecordScroll: function() {\n\t\t\tthis.setLastScrollEnabled = true;\n\t\t},\n\n\t\t// TODO consider the name here, since it's purpose specific\n\t\t_afterContentChange: function() {\n\t\t\t// once the page has changed, re-enable the scroll recording\n\t\t\tthis.setLastScrollEnabled = true;\n\n\t\t\t// remove any binding that previously existed on the get scroll\n\t\t\t// which may or may not be different than the scroll element\n\t\t\t// determined for this page previously\n\t\t\tthis._off( this.window, \"scrollstop\" );\n\n\t\t\t// determine and bind to the current scoll element which may be the\n\t\t\t// window or in the case of touch overflow the element touch overflow\n\t\t\tthis._on( this.window, { scrollstop: \"_delayedRecordScroll\" });\n\t\t},\n\n\t\t_recordScroll: function() {\n\t\t\t// this barrier prevents setting the scroll value based on\n\t\t\t// the browser scrolling the window based on a hashchange\n\t\t\tif ( !this.setLastScrollEnabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar active = this._getActiveHistory(),\n\t\t\t\tcurrentScroll, minScroll, defaultScroll;\n\n\t\t\tif ( active ) {\n\t\t\t\tcurrentScroll = this._getScroll();\n\t\t\t\tminScroll = this._getMinScroll();\n\t\t\t\tdefaultScroll = this._getDefaultScroll();\n\n\t\t\t\t// Set active page's lastScroll prop. If the location we're\n\t\t\t\t// scrolling to is less than minScrollBack, let it go.\n\t\t\t\tactive.lastScroll = currentScroll < minScroll ? defaultScroll : currentScroll;\n\t\t\t}\n\t\t},\n\n\t\t_delayedRecordScroll: function() {\n\t\t\tsetTimeout( $.proxy(this, \"_recordScroll\"), 100 );\n\t\t},\n\n\t\t_getScroll: function() {\n\t\t\treturn this.window.scrollTop();\n\t\t},\n\n\t\t_getMinScroll: function() {\n\t\t\treturn $.mobile.minScrollBack;\n\t\t},\n\n\t\t_getDefaultScroll: function() {\n\t\t\treturn $.mobile.defaultHomeScroll;\n\t\t},\n\n\t\t_filterNavigateEvents: function( e, data ) {\n\t\t\tvar url;\n\n\t\t\tif ( e.originalEvent && e.originalEvent.isDefaultPrevented() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\turl = e.originalEvent.type.indexOf( \"hashchange\" ) > -1 ? data.state.hash : data.state.url;\n\n\t\t\tif ( !url ) {\n\t\t\t\turl = this._getHash();\n\t\t\t}\n\n\t\t\tif ( !url || url === \"#\" || url.indexOf( \"#\" + $.mobile.path.uiStateKey ) === 0 ) {\n\t\t\t\turl = location.href;\n\t\t\t}\n\n\t\t\tthis._handleNavigate( url, data.state );\n\t\t},\n\n\t\t_getHash: function() {\n\t\t\treturn $.mobile.path.parseLocation().hash;\n\t\t},\n\n\t\t// TODO active page should be managed by the container (ie, it should be a property)\n\t\tgetActivePage: function() {\n\t\t\treturn this.activePage;\n\t\t},\n\n\t\t// TODO the first page should be a property set during _create using the logic\n\t\t//      that currently resides in init\n\t\t_getInitialContent: function() {\n\t\t\treturn $.mobile.firstPage;\n\t\t},\n\n\t\t// TODO each content container should have a history object\n\t\t_getHistory: function() {\n\t\t\treturn $.mobile.navigate.history;\n\t\t},\n\n\t\t_getActiveHistory: function() {\n\t\t\treturn this._getHistory().getActive();\n\t\t},\n\n\t\t// TODO the document base should be determined at creation\n\t\t_getDocumentBase: function() {\n\t\t\treturn $.mobile.path.documentBase;\n\t\t},\n\n\t\tback: function() {\n\t\t\tthis.go( -1 );\n\t\t},\n\n\t\tforward: function() {\n\t\t\tthis.go( 1 );\n\t\t},\n\n\t\tgo: function( steps ) {\n\n\t\t\t//if hashlistening is enabled use native history method\n\t\t\tif ( $.mobile.hashListeningEnabled ) {\n\t\t\t\twindow.history.go( steps );\n\t\t\t} else {\n\n\t\t\t\t//we are not listening to the hash so handle history internally\n\t\t\t\tvar activeIndex = $.mobile.navigate.history.activeIndex,\n\t\t\t\t\tindex = activeIndex + parseInt( steps, 10 ),\n\t\t\t\t\turl = $.mobile.navigate.history.stack[ index ].url,\n\t\t\t\t\tdirection = ( steps >= 1 )? \"forward\" : \"back\";\n\n\t\t\t\t//update the history object\n\t\t\t\t$.mobile.navigate.history.activeIndex = index;\n\t\t\t\t$.mobile.navigate.history.previousIndex = activeIndex;\n\n\t\t\t\t//change to the new page\n\t\t\t\tthis.change( url, { direction: direction, changeHash: false, fromHashChange: true } );\n\t\t\t}\n\t\t},\n\n\t\t// TODO rename _handleDestination\n\t\t_handleDestination: function( to ) {\n\t\t\tvar history;\n\n\t\t\t// clean the hash for comparison if it's a url\n\t\t\tif ( $.type(to) === \"string\" ) {\n\t\t\t\tto = $.mobile.path.stripHash( to );\n\t\t\t}\n\n\t\t\tif ( to ) {\n\t\t\t\thistory = this._getHistory();\n\n\t\t\t\t// At this point, 'to' can be one of 3 things, a cached page\n\t\t\t\t// element from a history stack entry, an id, or site-relative /\n\t\t\t\t// absolute URL. If 'to' is an id, we need to resolve it against\n\t\t\t\t// the documentBase, not the location.href, since the hashchange\n\t\t\t\t// could've been the result of a forward/backward navigation\n\t\t\t\t// that crosses from an external page/dialog to an internal\n\t\t\t\t// page/dialog.\n\t\t\t\t//\n\t\t\t\t// TODO move check to history object or path object?\n\t\t\t\tto = !$.mobile.path.isPath( to ) ? ( $.mobile.path.makeUrlAbsolute( \"#\" + to, this._getDocumentBase() ) ) : to;\n\t\t\t}\n\t\t\treturn to || this._getInitialContent();\n\t\t},\n\n\t\t_transitionFromHistory: function( direction, defaultTransition ) {\n\t\t\tvar history = this._getHistory(),\n\t\t\t\tentry = ( direction === \"back\" ? history.getLast() : history.getActive() );\n\n\t\t\treturn ( entry && entry.transition ) || defaultTransition;\n\t\t},\n\n\t\t_handleDialog: function( changePageOptions, data ) {\n\t\t\tvar to, active, activeContent = this.getActivePage();\n\n\t\t\t// If current active page is not a dialog skip the dialog and continue\n\t\t\t// in the same direction\n\t\t\t// Note: The dialog widget is deprecated as of 1.4.0 and will be removed in 1.5.0.\n\t\t\t// Thus, as of 1.5.0 activeContent.data( \"mobile-dialog\" ) will always evaluate to\n\t\t\t// falsy, so the second condition in the if-statement below can be removed altogether.\n\t\t\tif ( activeContent && !activeContent.data( \"mobile-dialog\" ) ) {\n\t\t\t\t// determine if we're heading forward or backward and continue\n\t\t\t\t// accordingly past the current dialog\n\t\t\t\tif ( data.direction === \"back\" ) {\n\t\t\t\t\tthis.back();\n\t\t\t\t} else {\n\t\t\t\t\tthis.forward();\n\t\t\t\t}\n\n\t\t\t\t// prevent changePage call\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\t// if the current active page is a dialog and we're navigating\n\t\t\t\t// to a dialog use the dialog objected saved in the stack\n\t\t\t\tto = data.pageUrl;\n\t\t\t\tactive = this._getActiveHistory();\n\n\t\t\t\t// make sure to set the role, transition and reversal\n\t\t\t\t// as most of this is lost by the domCache cleaning\n\t\t\t\t$.extend( changePageOptions, {\n\t\t\t\t\trole: active.role,\n\t\t\t\t\ttransition: this._transitionFromHistory(\n\t\t\t\t\t\tdata.direction,\n\t\t\t\t\t\tchangePageOptions.transition ),\n\t\t\t\t\treverse: data.direction === \"back\"\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn to;\n\t\t},\n\n\t\t_handleNavigate: function( url, data ) {\n\t\t\t//find first page via hash\n\t\t\t// TODO stripping the hash twice with handleUrl\n\t\t\tvar to = $.mobile.path.stripHash( url ), history = this._getHistory(),\n\n\t\t\t\t// transition is false if it's the first page, undefined\n\t\t\t\t// otherwise (and may be overridden by default)\n\t\t\t\ttransition = history.stack.length === 0 ? \"none\" :\n\t\t\t\t\tthis._transitionFromHistory( data.direction ),\n\n\t\t\t\t// default options for the changPage calls made after examining\n\t\t\t\t// the current state of the page and the hash, NOTE that the\n\t\t\t\t// transition is derived from the previous history entry\n\t\t\t\tchangePageOptions = {\n\t\t\t\t\tchangeHash: false,\n\t\t\t\t\tfromHashChange: true,\n\t\t\t\t\treverse: data.direction === \"back\"\n\t\t\t\t};\n\n\t\t\t$.extend( changePageOptions, data, {\n\t\t\t\ttransition: transition\n\t\t\t});\n\n\t\t\t// TODO move to _handleDestination ?\n\t\t\t// If this isn't the first page, if the current url is a dialog hash\n\t\t\t// key, and the initial destination isn't equal to the current target\n\t\t\t// page, use the special dialog handling\n\t\t\tif ( history.activeIndex > 0 &&\n\t\t\t\tto.indexOf( $.mobile.dialogHashKey ) > -1 ) {\n\n\t\t\t\tto = this._handleDialog( changePageOptions, data );\n\n\t\t\t\tif ( to === false ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis._changeContent( this._handleDestination( to ), changePageOptions );\n\t\t},\n\n\t\t_changeContent: function( to, opts ) {\n\t\t\t$.mobile.changePage( to, opts );\n\t\t},\n\n\t\t_getBase: function() {\n\t\t\treturn $.mobile.base;\n\t\t},\n\n\t\t_getNs: function() {\n\t\t\treturn $.mobile.ns;\n\t\t},\n\n\t\t_enhance: function( content, role ) {\n\t\t\t// TODO consider supporting a custom callback, and passing in\n\t\t\t// the settings which includes the role\n\t\t\treturn content.page({ role: role });\n\t\t},\n\n\t\t_include: function( page, settings ) {\n\t\t\t// append to page and enhance\n\t\t\tpage.appendTo( this.element );\n\n\t\t\t// use the page widget to enhance\n\t\t\tthis._enhance( page, settings.role );\n\n\t\t\t// remove page on hide\n\t\t\tpage.page( \"bindRemove\" );\n\t\t},\n\n\t\t_find: function( absUrl ) {\n\t\t\t// TODO consider supporting a custom callback\n\t\t\tvar fileUrl = this._createFileUrl( absUrl ),\n\t\t\t\tdataUrl = this._createDataUrl( absUrl ),\n\t\t\t\tpage, initialContent = this._getInitialContent();\n\n\t\t\t// Check to see if the page already exists in the DOM.\n\t\t\t// NOTE do _not_ use the :jqmData pseudo selector because parenthesis\n\t\t\t//      are a valid url char and it breaks on the first occurence\n\t\t\tpage = this.element\n\t\t\t\t.children( \"[data-\" + this._getNs() +\n\t\t\t\t\t\"url='\" + $.mobile.path.hashToSelector( dataUrl ) + \"']\" );\n\n\t\t\t// If we failed to find the page, check to see if the url is a\n\t\t\t// reference to an embedded page. If so, it may have been dynamically\n\t\t\t// injected by a developer, in which case it would be lacking a\n\t\t\t// data-url attribute and in need of enhancement.\n\t\t\tif ( page.length === 0 && dataUrl && !$.mobile.path.isPath( dataUrl ) ) {\n\t\t\t\tpage = this.element.children( $.mobile.path.hashToSelector(\"#\" + dataUrl) )\n\t\t\t\t\t.attr( \"data-\" + this._getNs() + \"url\", dataUrl )\n\t\t\t\t\t.jqmData( \"url\", dataUrl );\n\t\t\t}\n\n\t\t\t// If we failed to find a page in the DOM, check the URL to see if it\n\t\t\t// refers to the first page in the application. Also check to make sure\n\t\t\t// our cached-first-page is actually in the DOM. Some user deployed\n\t\t\t// apps are pruning the first page from the DOM for various reasons.\n\t\t\t// We check for this case here because we don't want a first-page with\n\t\t\t// an id falling through to the non-existent embedded page error case.\n\t\t\tif ( page.length === 0 &&\n\t\t\t\t$.mobile.path.isFirstPageUrl( fileUrl ) &&\n\t\t\t\tinitialContent &&\n\t\t\t\tinitialContent.parent().length ) {\n\t\t\t\tpage = $( initialContent );\n\t\t\t}\n\n\t\t\treturn page;\n\t\t},\n\n\t\t_getLoader: function() {\n\t\t\treturn $.mobile.loading();\n\t\t},\n\n\t\t_showLoading: function( delay, theme, msg, textonly ) {\n\t\t\t// This configurable timeout allows cached pages a brief\n\t\t\t// delay to load without showing a message\n\t\t\tif ( this._loadMsg ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._loadMsg = setTimeout($.proxy(function() {\n\t\t\t\tthis._getLoader().loader( \"show\", theme, msg, textonly );\n\t\t\t\tthis._loadMsg = 0;\n\t\t\t}, this), delay );\n\t\t},\n\n\t\t_hideLoading: function() {\n\t\t\t// Stop message show timer\n\t\t\tclearTimeout( this._loadMsg );\n\t\t\tthis._loadMsg = 0;\n\n\t\t\t// Hide loading message\n\t\t\tthis._getLoader().loader( \"hide\" );\n\t\t},\n\n\t\t_showError: function() {\n\t\t\t// make sure to remove the current loading message\n\t\t\tthis._hideLoading();\n\n\t\t\t// show the error message\n\t\t\tthis._showLoading( 0, $.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true );\n\n\t\t\t// hide the error message after a delay\n\t\t\t// TODO configuration\n\t\t\tsetTimeout( $.proxy(this, \"_hideLoading\"), 1500 );\n\t\t},\n\n\t\t_parse: function( html, fileUrl ) {\n\t\t\t// TODO consider allowing customization of this method. It's very JQM specific\n\t\t\tvar page, all = $( \"<div></div>\" );\n\n\t\t\t//workaround to allow scripts to execute when included in page divs\n\t\t\tall.get( 0 ).innerHTML = html;\n\n\t\t\tpage = all.find( \":jqmData(role='page'), :jqmData(role='dialog')\" ).first();\n\n\t\t\t//if page elem couldn't be found, create one and insert the body element's contents\n\t\t\tif ( !page.length ) {\n\t\t\t\tpage = $( \"<div data-\" + this._getNs() + \"role='page'>\" +\n\t\t\t\t\t( html.split( /<\\/?body[^>]*>/gmi )[1] || \"\" ) +\n\t\t\t\t\t\"</div>\" );\n\t\t\t}\n\n\t\t\t// TODO tagging a page with external to make sure that embedded pages aren't\n\t\t\t// removed by the various page handling code is bad. Having page handling code\n\t\t\t// in many places is bad. Solutions post 1.0\n\t\t\tpage.attr( \"data-\" + this._getNs() + \"url\", this._createDataUrl( fileUrl ) )\n\t\t\t\t.attr( \"data-\" + this._getNs() + \"external-page\", true );\n\n\t\t\treturn page;\n\t\t},\n\n\t\t_setLoadedTitle: function( page, html ) {\n\t\t\t//page title regexp\n\t\t\tvar newPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1;\n\n\t\t\tif ( newPageTitle && !page.jqmData(\"title\") ) {\n\t\t\t\tnewPageTitle = $( \"<div>\" + newPageTitle + \"</div>\" ).text();\n\t\t\t\tpage.jqmData( \"title\", newPageTitle );\n\t\t\t}\n\t\t},\n\n\t\t_isRewritableBaseTag: function() {\n\t\t\treturn $.mobile.dynamicBaseEnabled && !$.support.dynamicBaseTag;\n\t\t},\n\n\t\t_createDataUrl: function( absoluteUrl ) {\n\t\t\treturn $.mobile.path.convertUrlToDataUrl( absoluteUrl );\n\t\t},\n\n\t\t_createFileUrl: function( absoluteUrl ) {\n\t\t\treturn $.mobile.path.getFilePath( absoluteUrl );\n\t\t},\n\n\t\t_triggerWithDeprecated: function( name, data, page ) {\n\t\t\tvar deprecatedEvent = $.Event( \"page\" + name ),\n\t\t\t\tnewEvent = $.Event( this.widgetName + name );\n\n\t\t\t// DEPRECATED\n\t\t\t// trigger the old deprecated event on the page if it's provided\n\t\t\t( page || this.element ).trigger( deprecatedEvent, data );\n\n\t\t\t// use the widget trigger method for the new content* event\n\t\t\tthis._trigger( name, newEvent, data );\n\n\t\t\treturn {\n\t\t\t\tdeprecatedEvent: deprecatedEvent,\n\t\t\t\tevent: newEvent\n\t\t\t};\n\t\t},\n\n\t\t// TODO it would be nice to split this up more but everything appears to be \"one off\"\n\t\t//      or require ordering such that other bits are sprinkled in between parts that\n\t\t//      could be abstracted out as a group\n\t\t_loadSuccess: function( absUrl, triggerData, settings, deferred ) {\n\t\t\tvar fileUrl = this._createFileUrl( absUrl );\n\n\t\t\treturn $.proxy(function( html, textStatus, xhr ) {\n\t\t\t\t//pre-parse html to check for a data-url,\n\t\t\t\t//use it as the new fileUrl, base path, etc\n\t\t\t\tvar content,\n\n\t\t\t\t\t// TODO handle dialogs again\n\t\t\t\t\tpageElemRegex = new RegExp( \"(<[^>]+\\\\bdata-\" + this._getNs() + \"role=[\\\"']?page[\\\"']?[^>]*>)\" ),\n\n\t\t\t\t\tdataUrlRegex = new RegExp( \"\\\\bdata-\" + this._getNs() + \"url=[\\\"']?([^\\\"'>]*)[\\\"']?\" );\n\n\t\t\t\t// data-url must be provided for the base tag so resource requests\n\t\t\t\t// can be directed to the correct url. loading into a temprorary\n\t\t\t\t// element makes these requests immediately\n\t\t\t\tif ( pageElemRegex.test( html ) &&\n\t\t\t\t\tRegExp.$1 &&\n\t\t\t\t\tdataUrlRegex.test( RegExp.$1 ) &&\n\t\t\t\t\tRegExp.$1 ) {\n\t\t\t\t\tfileUrl = $.mobile.path.getFilePath( $(\"<div>\" + RegExp.$1 + \"</div>\").text() );\n\n\t\t\t\t\t// We specify that, if a data-url attribute is given on the page div, its value\n\t\t\t\t\t// must be given non-URL-encoded. However, in this part of the code, fileUrl is\n\t\t\t\t\t// assumed to be URL-encoded, so we URL-encode the retrieved value here\n\t\t\t\t\tfileUrl = this.window[ 0 ].encodeURIComponent( fileUrl );\n\t\t\t\t}\n\n\t\t\t\t//dont update the base tag if we are prefetching\n\t\t\t\tif ( settings.prefetch === undefined ) {\n\t\t\t\t\tthis._getBase().set( fileUrl );\n\t\t\t\t}\n\n\t\t\t\tcontent = this._parse( html, fileUrl );\n\n\t\t\t\tthis._setLoadedTitle( content, html );\n\n\t\t\t\t// Add the content reference and xhr to our triggerData.\n\t\t\t\ttriggerData.xhr = xhr;\n\t\t\t\ttriggerData.textStatus = textStatus;\n\n\t\t\t\t// DEPRECATED\n\t\t\t\ttriggerData.page = content;\n\n\t\t\t\ttriggerData.content = content;\n\n\t\t\t\ttriggerData.toPage = content;\n\n\t\t\t\t// If the default behavior is prevented, stop here!\n\t\t\t\t// Note that it is the responsibility of the listener/handler\n\t\t\t\t// that called preventDefault(), to resolve/reject the\n\t\t\t\t// deferred object within the triggerData.\n\t\t\t\tif ( this._triggerWithDeprecated( \"load\", triggerData ).event.isDefaultPrevented() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// rewrite src and href attrs to use a base url if the base tag won't work\n\t\t\t\tif ( this._isRewritableBaseTag() && content ) {\n\t\t\t\t\tthis._getBase().rewrite( fileUrl, content );\n\t\t\t\t}\n\n\t\t\t\tthis._include( content, settings );\n\n\t\t\t\t// Remove loading message.\n\t\t\t\tif ( settings.showLoadMsg ) {\n\t\t\t\t\tthis._hideLoading();\n\t\t\t\t}\n\n\t\t\t\tdeferred.resolve( absUrl, settings, content );\n\t\t\t}, this);\n\t\t},\n\n\t\t_loadDefaults: {\n\t\t\ttype: \"get\",\n\t\t\tdata: undefined,\n\n\t\t\t// DEPRECATED\n\t\t\treloadPage: false,\n\n\t\t\treload: false,\n\n\t\t\t// By default we rely on the role defined by the @data-role attribute.\n\t\t\trole: undefined,\n\n\t\t\tshowLoadMsg: false,\n\n\t\t\t// This delay allows loads that pull from browser cache to\n\t\t\t// occur without showing the loading message.\n\t\t\tloadMsgDelay: 50\n\t\t},\n\n\t\tload: function( url, options ) {\n\t\t\t// This function uses deferred notifications to let callers\n\t\t\t// know when the content is done loading, or if an error has occurred.\n\t\t\tvar deferred = ( options && options.deferred ) || $.Deferred(),\n\n\t\t\t\t// Examining the option \"reloadPage\" passed by the user is deprecated as of 1.4.0\n\t\t\t\t// and will be removed in 1.5.0.\n\t\t\t\t// Copy option \"reloadPage\" to \"reload\", but only if option \"reload\" is not present\n\t\t\t\treloadOptionExtension =\n\t\t\t\t\t( ( options && options.reload === undefined &&\n\t\t\t\t\t\toptions.reloadPage !== undefined ) ?\n\t\t\t\t\t\t\t{ reload: options.reloadPage } : {} ),\n\n\t\t\t\t// The default load options with overrides specified by the caller.\n\t\t\t\tsettings = $.extend( {}, this._loadDefaults, options, reloadOptionExtension ),\n\n\t\t\t\t// The DOM element for the content after it has been loaded.\n\t\t\t\tcontent = null,\n\n\t\t\t\t// The absolute version of the URL passed into the function. This\n\t\t\t\t// version of the URL may contain dialog/subcontent params in it.\n\t\t\t\tabsUrl = $.mobile.path.makeUrlAbsolute( url, this._findBaseWithDefault() ),\n\t\t\t\tfileUrl, dataUrl, pblEvent, triggerData;\n\n\t\t\t// If the caller provided data, and we're using \"get\" request,\n\t\t\t// append the data to the URL.\n\t\t\tif ( settings.data && settings.type === \"get\" ) {\n\t\t\t\tabsUrl = $.mobile.path.addSearchParams( absUrl, settings.data );\n\t\t\t\tsettings.data = undefined;\n\t\t\t}\n\n\t\t\t// If the caller is using a \"post\" request, reload must be true\n\t\t\tif ( settings.data && settings.type === \"post\" ) {\n\t\t\t\tsettings.reload = true;\n\t\t\t}\n\n\t\t\t// The absolute version of the URL minus any dialog/subcontent params.\n\t\t\t// In otherwords the real URL of the content to be loaded.\n\t\t\tfileUrl = this._createFileUrl( absUrl );\n\n\t\t\t// The version of the Url actually stored in the data-url attribute of\n\t\t\t// the content. For embedded content, it is just the id of the page. For\n\t\t\t// content within the same domain as the document base, it is the site\n\t\t\t// relative path. For cross-domain content (Phone Gap only) the entire\n\t\t\t// absolute Url is used to load the content.\n\t\t\tdataUrl = this._createDataUrl( absUrl );\n\n\t\t\tcontent = this._find( absUrl );\n\n\t\t\t// If it isn't a reference to the first content and refers to missing\n\t\t\t// embedded content reject the deferred and return\n\t\t\tif ( content.length === 0 &&\n\t\t\t\t$.mobile.path.isEmbeddedPage(fileUrl) &&\n\t\t\t\t!$.mobile.path.isFirstPageUrl(fileUrl) ) {\n\t\t\t\tdeferred.reject( absUrl, settings );\n\t\t\t\treturn deferred.promise();\n\t\t\t}\n\n\t\t\t// Reset base to the default document base\n\t\t\t// TODO figure out why we doe this\n\t\t\tthis._getBase().reset();\n\n\t\t\t// If the content we are interested in is already in the DOM,\n\t\t\t// and the caller did not indicate that we should force a\n\t\t\t// reload of the file, we are done. Resolve the deferrred so that\n\t\t\t// users can bind to .done on the promise\n\t\t\tif ( content.length && !settings.reload ) {\n\t\t\t\tthis._enhance( content, settings.role );\n\t\t\t\tdeferred.resolve( absUrl, settings, content );\n\n\t\t\t\t//if we are reloading the content make sure we update\n\t\t\t\t// the base if its not a prefetch\n\t\t\t\tif ( !settings.prefetch ) {\n\t\t\t\t\tthis._getBase().set(url);\n\t\t\t\t}\n\n\t\t\t\treturn deferred.promise();\n\t\t\t}\n\n\t\t\ttriggerData = {\n\t\t\t\turl: url,\n\t\t\t\tabsUrl: absUrl,\n\t\t\t\ttoPage: url,\n\t\t\t\tprevPage: options ? options.fromPage : undefined,\n\t\t\t\tdataUrl: dataUrl,\n\t\t\t\tdeferred: deferred,\n\t\t\t\toptions: settings\n\t\t\t};\n\n\t\t\t// Let listeners know we're about to load content.\n\t\t\tpblEvent = this._triggerWithDeprecated( \"beforeload\", triggerData );\n\n\t\t\t// If the default behavior is prevented, stop here!\n\t\t\tif ( pblEvent.deprecatedEvent.isDefaultPrevented() ||\n\t\t\t\tpblEvent.event.isDefaultPrevented() ) {\n\t\t\t\treturn deferred.promise();\n\t\t\t}\n\n\t\t\tif ( settings.showLoadMsg ) {\n\t\t\t\tthis._showLoading( settings.loadMsgDelay );\n\t\t\t}\n\n\t\t\t// Reset base to the default document base.\n\t\t\t// only reset if we are not prefetching\n\t\t\tif ( settings.prefetch === undefined ) {\n\t\t\t\tthis._getBase().reset();\n\t\t\t}\n\n\t\t\tif ( !( $.mobile.allowCrossDomainPages ||\n\t\t\t\t$.mobile.path.isSameDomain($.mobile.path.documentUrl, absUrl ) ) ) {\n\t\t\t\tdeferred.reject( absUrl, settings );\n\t\t\t\treturn deferred.promise();\n\t\t\t}\n\n\t\t\t// Load the new content.\n\t\t\t$.ajax({\n\t\t\t\turl: fileUrl,\n\t\t\t\ttype: settings.type,\n\t\t\t\tdata: settings.data,\n\t\t\t\tcontentType: settings.contentType,\n\t\t\t\tdataType: \"html\",\n\t\t\t\tsuccess: this._loadSuccess( absUrl, triggerData, settings, deferred ),\n\t\t\t\terror: this._loadError( absUrl, triggerData, settings, deferred )\n\t\t\t});\n\n\t\t\treturn deferred.promise();\n\t\t},\n\n\t\t_loadError: function( absUrl, triggerData, settings, deferred ) {\n\t\t\treturn $.proxy(function( xhr, textStatus, errorThrown ) {\n\t\t\t\t//set base back to current path\n\t\t\t\tthis._getBase().set( $.mobile.path.get() );\n\n\t\t\t\t// Add error info to our triggerData.\n\t\t\t\ttriggerData.xhr = xhr;\n\t\t\t\ttriggerData.textStatus = textStatus;\n\t\t\t\ttriggerData.errorThrown = errorThrown;\n\n\t\t\t\t// Let listeners know the page load failed.\n\t\t\t\tvar plfEvent = this._triggerWithDeprecated( \"loadfailed\", triggerData );\n\n\t\t\t\t// If the default behavior is prevented, stop here!\n\t\t\t\t// Note that it is the responsibility of the listener/handler\n\t\t\t\t// that called preventDefault(), to resolve/reject the\n\t\t\t\t// deferred object within the triggerData.\n\t\t\t\tif ( plfEvent.deprecatedEvent.isDefaultPrevented() ||\n\t\t\t\t\tplfEvent.event.isDefaultPrevented() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Remove loading message.\n\t\t\t\tif ( settings.showLoadMsg ) {\n\t\t\t\t\tthis._showError();\n\t\t\t\t}\n\n\t\t\t\tdeferred.reject( absUrl, settings );\n\t\t\t}, this);\n\t\t},\n\n\t\t_getTransitionHandler: function( transition ) {\n\t\t\ttransition = $.mobile._maybeDegradeTransition( transition );\n\n\t\t\t//find the transition handler for the specified transition. If there\n\t\t\t//isn't one in our transitionHandlers dictionary, use the default one.\n\t\t\t//call the handler immediately to kick-off the transition.\n\t\t\treturn $.mobile.transitionHandlers[ transition ] || $.mobile.defaultTransitionHandler;\n\t\t},\n\n\t\t// TODO move into transition handlers?\n\t\t_triggerCssTransitionEvents: function( to, from, prefix ) {\n\t\t\tvar samePage = false;\n\n\t\t\tprefix = prefix || \"\";\n\n\t\t\t// TODO decide if these events should in fact be triggered on the container\n\t\t\tif ( from ) {\n\n\t\t\t\t//Check if this is a same page transition and tell the handler in page\n\t\t\t\tif( to[0] === from[0] ){\n\t\t\t\t\tsamePage = true;\n\t\t\t\t}\n\n\t\t\t\t//trigger before show/hide events\n\t\t\t\t// TODO deprecate nextPage in favor of next\n\t\t\t\tthis._triggerWithDeprecated( prefix + \"hide\", {\n\n\t\t\t\t\t// Deprecated in 1.4 remove in 1.5\n\t\t\t\t\tnextPage: to,\n\t\t\t\t\ttoPage: to,\n\t\t\t\t\tprevPage: from,\n\t\t\t\t\tsamePage: samePage\n\t\t\t\t}, from );\n\t\t\t}\n\n\t\t\t// TODO deprecate prevPage in favor of previous\n\t\t\tthis._triggerWithDeprecated( prefix + \"show\", {\n\t\t\t\tprevPage: from || $( \"\" ),\n\t\t\t\ttoPage: to\n\t\t\t}, to );\n\t\t},\n\n\t\t// TODO make private once change has been defined in the widget\n\t\t_cssTransition: function( to, from, options ) {\n\t\t\tvar transition = options.transition,\n\t\t\t\treverse = options.reverse,\n\t\t\t\tdeferred = options.deferred,\n\t\t\t\tTransitionHandler,\n\t\t\t\tpromise;\n\n\t\t\tthis._triggerCssTransitionEvents( to, from, \"before\" );\n\n\t\t\t// TODO put this in a binding to events *outside* the widget\n\t\t\tthis._hideLoading();\n\n\t\t\tTransitionHandler = this._getTransitionHandler( transition );\n\n\t\t\tpromise = ( new TransitionHandler( transition, reverse, to, from ) ).transition();\n\n\t\t\tpromise.done( $.proxy( function() {\n\t\t\t\tthis._triggerCssTransitionEvents( to, from );\n\t\t\t}, this ));\n\n\t\t\t// TODO temporary accomodation of argument deferred\n\t\t\tpromise.done(function() {\n\t\t\t\tdeferred.resolve.apply( deferred, arguments );\n\t\t\t});\n\t\t},\n\n\t\t_releaseTransitionLock: function() {\n\t\t\t//release transition lock so navigation is free again\n\t\t\tisPageTransitioning = false;\n\t\t\tif ( pageTransitionQueue.length > 0 ) {\n\t\t\t\t$.mobile.changePage.apply( null, pageTransitionQueue.pop() );\n\t\t\t}\n\t\t},\n\n\t\t_removeActiveLinkClass: function( force ) {\n\t\t\t//clear out the active button state\n\t\t\t$.mobile.removeActiveLinkClass( force );\n\t\t},\n\n\t\t_loadUrl: function( to, triggerData, settings ) {\n\t\t\t// preserve the original target as the dataUrl value will be\n\t\t\t// simplified eg, removing ui-state, and removing query params\n\t\t\t// from the hash this is so that users who want to use query\n\t\t\t// params have access to them in the event bindings for the page\n\t\t\t// life cycle See issue #5085\n\t\t\tsettings.target = to;\n\t\t\tsettings.deferred = $.Deferred();\n\n\t\t\tthis.load( to, settings );\n\n\t\t\tsettings.deferred.done($.proxy(function( url, options, content ) {\n\t\t\t\tisPageTransitioning = false;\n\n\t\t\t\t// store the original absolute url so that it can be provided\n\t\t\t\t// to events in the triggerData of the subsequent changePage call\n\t\t\t\toptions.absUrl = triggerData.absUrl;\n\n\t\t\t\tthis.transition( content, triggerData, options );\n\t\t\t}, this));\n\n\t\t\tsettings.deferred.fail($.proxy(function(/* url, options */) {\n\t\t\t\tthis._removeActiveLinkClass( true );\n\t\t\t\tthis._releaseTransitionLock();\n\t\t\t\tthis._triggerWithDeprecated( \"changefailed\", triggerData );\n\t\t\t}, this));\n\t\t},\n\n\t\t_triggerPageBeforeChange: function( to, triggerData, settings ) {\n\t\t\tvar returnEvents;\n\n\t\t\ttriggerData.prevPage = this.activePage;\n\t\t\t$.extend( triggerData, {\n\t\t\t\ttoPage: to,\n\t\t\t\toptions: settings\n\t\t\t});\n\n\t\t\t// NOTE: preserve the original target as the dataUrl value will be\n\t\t\t// simplified eg, removing ui-state, and removing query params from\n\t\t\t// the hash this is so that users who want to use query params have\n\t\t\t// access to them in the event bindings for the page life cycle\n\t\t\t// See issue #5085\n\t\t\tif ( $.type(to) === \"string\" ) {\n\t\t\t\t// if the toPage is a string simply convert it\n\t\t\t\ttriggerData.absUrl = $.mobile.path.makeUrlAbsolute( to, this._findBaseWithDefault() );\n\t\t\t} else {\n\t\t\t\t// if the toPage is a jQuery object grab the absolute url stored\n\t\t\t\t// in the loadPage callback where it exists\n\t\t\t\ttriggerData.absUrl = settings.absUrl;\n\t\t\t}\n\n\t\t\t// Let listeners know we're about to change the current page.\n\t\t\treturnEvents = this._triggerWithDeprecated( \"beforechange\", triggerData );\n\n\t\t\t// If the default behavior is prevented, stop here!\n\t\t\tif ( returnEvents.event.isDefaultPrevented() ||\n\t\t\t\treturnEvents.deprecatedEvent.isDefaultPrevented() ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t},\n\n\t\tchange: function( to, options ) {\n\t\t\t// If we are in the midst of a transition, queue the current request.\n\t\t\t// We'll call changePage() once we're done with the current transition\n\t\t\t// to service the request.\n\t\t\tif ( isPageTransitioning ) {\n\t\t\t\tpageTransitionQueue.unshift( arguments );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar settings = $.extend( {}, $.mobile.changePage.defaults, options ),\n\t\t\t\ttriggerData = {};\n\n\t\t\t// Make sure we have a fromPage.\n\t\t\tsettings.fromPage = settings.fromPage || this.activePage;\n\n\t\t\t// if the page beforechange default is prevented return early\n\t\t\tif ( !this._triggerPageBeforeChange(to, triggerData, settings) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// We allow \"pagebeforechange\" observers to modify the to in\n\t\t\t// the trigger data to allow for redirects. Make sure our to is\n\t\t\t// updated. We also need to re-evaluate whether it is a string,\n\t\t\t// because an object can also be replaced by a string\n\t\t\tto = triggerData.toPage;\n\n\t\t\t// If the caller passed us a url, call loadPage()\n\t\t\t// to make sure it is loaded into the DOM. We'll listen\n\t\t\t// to the promise object it returns so we know when\n\t\t\t// it is done loading or if an error ocurred.\n\t\t\tif ( $.type(to) === \"string\" ) {\n\t\t\t\t// Set the isPageTransitioning flag to prevent any requests from\n\t\t\t\t// entering this method while we are in the midst of loading a page\n\t\t\t\t// or transitioning.\n\t\t\t\tisPageTransitioning = true;\n\n\t\t\t\tthis._loadUrl( to, triggerData, settings );\n\t\t\t} else {\n\t\t\t\tthis.transition( to, triggerData, settings );\n\t\t\t}\n\t\t},\n\n\t\ttransition: function( toPage, triggerData, settings ) {\n\t\t\tvar fromPage, url, pageUrl, fileUrl,\n\t\t\t\tactive, activeIsInitialPage,\n\t\t\t\thistoryDir, pageTitle, isDialog,\n\t\t\t\talreadyThere, newPageTitle,\n\t\t\t\tparams,\tcssTransitionDeferred,\n\t\t\t\tbeforeTransition;\n\n\t\t\t// If we are in the midst of a transition, queue the current request.\n\t\t\t// We'll call changePage() once we're done with the current transition\n\t\t\t// to service the request.\n\t\t\tif ( isPageTransitioning ) {\n\t\t\t\t// make sure to only queue the to and settings values so the arguments\n\t\t\t\t// work with a call to the change method\n\t\t\t\tpageTransitionQueue.unshift( [toPage, settings] );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// DEPRECATED - this call only, in favor of the before transition\n\t\t\t// if the page beforechange default is prevented return early\n\t\t\tif ( !this._triggerPageBeforeChange(toPage, triggerData, settings) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttriggerData.prevPage = settings.fromPage;\n\t\t\t// if the (content|page)beforetransition default is prevented return early\n\t\t\t// Note, we have to check for both the deprecated and new events\n\t\t\tbeforeTransition = this._triggerWithDeprecated( \"beforetransition\", triggerData );\n\t\t\tif (beforeTransition.deprecatedEvent.isDefaultPrevented() ||\n\t\t\t\tbeforeTransition.event.isDefaultPrevented() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the isPageTransitioning flag to prevent any requests from\n\t\t\t// entering this method while we are in the midst of loading a page\n\t\t\t// or transitioning.\n\t\t\tisPageTransitioning = true;\n\n\t\t\t// If we are going to the first-page of the application, we need to make\n\t\t\t// sure settings.dataUrl is set to the application document url. This allows\n\t\t\t// us to avoid generating a document url with an id hash in the case where the\n\t\t\t// first-page of the document has an id attribute specified.\n\t\t\tif ( toPage[ 0 ] === $.mobile.firstPage[ 0 ] && !settings.dataUrl ) {\n\t\t\t\tsettings.dataUrl = $.mobile.path.documentUrl.hrefNoHash;\n\t\t\t}\n\n\t\t\t// The caller passed us a real page DOM element. Update our\n\t\t\t// internal state and then trigger a transition to the page.\n\t\t\tfromPage = settings.fromPage;\n\t\t\turl = ( settings.dataUrl && $.mobile.path.convertUrlToDataUrl(settings.dataUrl) ) ||\n\t\t\t\ttoPage.jqmData( \"url\" );\n\n\t\t\t// The pageUrl var is usually the same as url, except when url is obscured\n\t\t\t// as a dialog url. pageUrl always contains the file path\n\t\t\tpageUrl = url;\n\t\t\tfileUrl = $.mobile.path.getFilePath( url );\n\t\t\tactive = $.mobile.navigate.history.getActive();\n\t\t\tactiveIsInitialPage = $.mobile.navigate.history.activeIndex === 0;\n\t\t\thistoryDir = 0;\n\t\t\tpageTitle = document.title;\n\t\t\tisDialog = ( settings.role === \"dialog\" ||\n\t\t\t\ttoPage.jqmData( \"role\" ) === \"dialog\" ) &&\n\t\t\t\ttoPage.jqmData( \"dialog\" ) !== true;\n\n\t\t\t// By default, we prevent changePage requests when the fromPage and toPage\n\t\t\t// are the same element, but folks that generate content\n\t\t\t// manually/dynamically and reuse pages want to be able to transition to\n\t\t\t// the same page. To allow this, they will need to change the default\n\t\t\t// value of allowSamePageTransition to true, *OR*, pass it in as an\n\t\t\t// option when they manually call changePage(). It should be noted that\n\t\t\t// our default transition animations assume that the formPage and toPage\n\t\t\t// are different elements, so they may behave unexpectedly. It is up to\n\t\t\t// the developer that turns on the allowSamePageTransitiona option to\n\t\t\t// either turn off transition animations, or make sure that an appropriate\n\t\t\t// animation transition is used.\n\t\t\tif ( fromPage && fromPage[0] === toPage[0] &&\n\t\t\t\t!settings.allowSamePageTransition ) {\n\n\t\t\t\tisPageTransitioning = false;\n\t\t\t\tthis._triggerWithDeprecated( \"transition\", triggerData );\n\t\t\t\tthis._triggerWithDeprecated( \"change\", triggerData );\n\n\t\t\t\t// Even if there is no page change to be done, we should keep the\n\t\t\t\t// urlHistory in sync with the hash changes\n\t\t\t\tif ( settings.fromHashChange ) {\n\t\t\t\t\t$.mobile.navigate.history.direct({ url: url });\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// We need to make sure the page we are given has already been enhanced.\n\t\t\ttoPage.page({ role: settings.role });\n\n\t\t\t// If the changePage request was sent from a hashChange event, check to\n\t\t\t// see if the page is already within the urlHistory stack. If so, we'll\n\t\t\t// assume the user hit the forward/back button and will try to match the\n\t\t\t// transition accordingly.\n\t\t\tif ( settings.fromHashChange ) {\n\t\t\t\thistoryDir = settings.direction === \"back\" ? -1 : 1;\n\t\t\t}\n\n\t\t\t// Kill the keyboard.\n\t\t\t// XXX_jblas: We need to stop crawling the entire document to kill focus.\n\t\t\t//            Instead, we should be tracking focus with a delegate()\n\t\t\t//            handler so we already have the element in hand at this\n\t\t\t//            point.\n\t\t\t// Wrap this in a try/catch block since IE9 throw \"Unspecified error\" if\n\t\t\t// document.activeElement is undefined when we are in an IFrame.\n\t\t\ttry {\n\t\t\t\tif ( document.activeElement &&\n\t\t\t\t\tdocument.activeElement.nodeName.toLowerCase() !== \"body\" ) {\n\n\t\t\t\t\t$( document.activeElement ).blur();\n\t\t\t\t} else {\n\t\t\t\t\t$( \"input:focus, textarea:focus, select:focus\" ).blur();\n\t\t\t\t}\n\t\t\t} catch( e ) {}\n\n\t\t\t// Record whether we are at a place in history where a dialog used to be -\n\t\t\t// if so, do not add a new history entry and do not change the hash either\n\t\t\talreadyThere = false;\n\n\t\t\t// If we're displaying the page as a dialog, we don't want the url\n\t\t\t// for the dialog content to be used in the hash. Instead, we want\n\t\t\t// to append the dialogHashKey to the url of the current page.\n\t\t\tif ( isDialog && active ) {\n\t\t\t\t// on the initial page load active.url is undefined and in that case\n\t\t\t\t// should be an empty string. Moving the undefined -> empty string back\n\t\t\t\t// into urlHistory.addNew seemed imprudent given undefined better\n\t\t\t\t// represents the url state\n\n\t\t\t\t// If we are at a place in history that once belonged to a dialog, reuse\n\t\t\t\t// this state without adding to urlHistory and without modifying the\n\t\t\t\t// hash. However, if a dialog is already displayed at this point, and\n\t\t\t\t// we're about to display another dialog, then we must add another hash\n\t\t\t\t// and history entry on top so that one may navigate back to the\n\t\t\t\t// original dialog\n\t\t\t\tif ( active.url &&\n\t\t\t\t\tactive.url.indexOf( $.mobile.dialogHashKey ) > -1 &&\n\t\t\t\t\tthis.activePage &&\n\t\t\t\t\t!this.activePage.hasClass( \"ui-dialog\" ) &&\n\t\t\t\t\t$.mobile.navigate.history.activeIndex > 0 ) {\n\n\t\t\t\t\tsettings.changeHash = false;\n\t\t\t\t\talreadyThere = true;\n\t\t\t\t}\n\n\t\t\t\t// Normally, we tack on a dialog hash key, but if this is the location\n\t\t\t\t// of a stale dialog, we reuse the URL from the entry\n\t\t\t\turl = ( active.url || \"\" );\n\n\t\t\t\t// account for absolute urls instead of just relative urls use as hashes\n\t\t\t\tif ( !alreadyThere && url.indexOf(\"#\") > -1 ) {\n\t\t\t\t\turl += $.mobile.dialogHashKey;\n\t\t\t\t} else {\n\t\t\t\t\turl += \"#\" + $.mobile.dialogHashKey;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if title element wasn't found, try the page div data attr too\n\t\t\t// If this is a deep-link or a reload ( active === undefined ) then just\n\t\t\t// use pageTitle\n\t\t\tnewPageTitle = ( !active ) ? pageTitle : toPage.jqmData( \"title\" ) ||\n\t\t\t\ttoPage.children( \":jqmData(role='header')\" ).find( \".ui-title\" ).text();\n\t\t\tif ( !!newPageTitle && pageTitle === document.title ) {\n\t\t\t\tpageTitle = newPageTitle;\n\t\t\t}\n\t\t\tif ( !toPage.jqmData( \"title\" ) ) {\n\t\t\t\ttoPage.jqmData( \"title\", pageTitle );\n\t\t\t}\n\n\t\t\t// Make sure we have a transition defined.\n\t\t\tsettings.transition = settings.transition ||\n\t\t\t\t( ( historyDir && !activeIsInitialPage ) ? active.transition : undefined ) ||\n\t\t\t\t( isDialog ? $.mobile.defaultDialogTransition : $.mobile.defaultPageTransition );\n\n\t\t\t//add page to history stack if it's not back or forward\n\t\t\tif ( !historyDir && alreadyThere ) {\n\t\t\t\t$.mobile.navigate.history.getActive().pageUrl = pageUrl;\n\t\t\t}\n\n\t\t\t// Set the location hash.\n\t\t\tif ( url && !settings.fromHashChange ) {\n\n\t\t\t\t// rebuilding the hash here since we loose it earlier on\n\t\t\t\t// TODO preserve the originally passed in path\n\t\t\t\tif ( !$.mobile.path.isPath( url ) && url.indexOf( \"#\" ) < 0 ) {\n\t\t\t\t\turl = \"#\" + url;\n\t\t\t\t}\n\n\t\t\t\t// TODO the property names here are just silly\n\t\t\t\tparams = {\n\t\t\t\t\ttransition: settings.transition,\n\t\t\t\t\ttitle: pageTitle,\n\t\t\t\t\tpageUrl: pageUrl,\n\t\t\t\t\trole: settings.role\n\t\t\t\t};\n\n\t\t\t\tif ( settings.changeHash !== false && $.mobile.hashListeningEnabled ) {\n\t\t\t\t\t$.mobile.navigate( this.window[ 0 ].encodeURI( url ), params, true);\n\t\t\t\t} else if ( toPage[ 0 ] !== $.mobile.firstPage[ 0 ] ) {\n\t\t\t\t\t$.mobile.navigate.history.add( url, params );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//set page title\n\t\t\tdocument.title = pageTitle;\n\n\t\t\t//set \"toPage\" as activePage deprecated in 1.4 remove in 1.5\n\t\t\t$.mobile.activePage = toPage;\n\n\t\t\t//new way to handle activePage\n\t\t\tthis.activePage = toPage;\n\n\t\t\t// If we're navigating back in the URL history, set reverse accordingly.\n\t\t\tsettings.reverse = settings.reverse || historyDir < 0;\n\n\t\t\tcssTransitionDeferred = $.Deferred();\n\n\t\t\tthis._cssTransition(toPage, fromPage, {\n\t\t\t\ttransition: settings.transition,\n\t\t\t\treverse: settings.reverse,\n\t\t\t\tdeferred: cssTransitionDeferred\n\t\t\t});\n\n\t\t\tcssTransitionDeferred.done($.proxy(function( name, reverse, $to, $from, alreadyFocused ) {\n\t\t\t\t$.mobile.removeActiveLinkClass();\n\n\t\t\t\t//if there's a duplicateCachedPage, remove it from the DOM now that it's hidden\n\t\t\t\tif ( settings.duplicateCachedPage ) {\n\t\t\t\t\tsettings.duplicateCachedPage.remove();\n\t\t\t\t}\n\n\t\t\t\t// despite visibility: hidden addresses issue #2965\n\t\t\t\t// https://github.com/jquery/jquery-mobile/issues/2965\n\t\t\t\tif ( !alreadyFocused ) {\n\t\t\t\t\t$.mobile.focusPage( toPage );\n\t\t\t\t}\n\n\t\t\t\tthis._releaseTransitionLock();\n\t\t\t\tthis._triggerWithDeprecated( \"transition\", triggerData );\n\t\t\t\tthis._triggerWithDeprecated( \"change\", triggerData );\n\t\t\t}, this));\n\t\t},\n\n\t\t// determine the current base url\n\t\t_findBaseWithDefault: function() {\n\t\t\tvar closestBase = ( this.activePage &&\n\t\t\t$.mobile.getClosestBaseUrl( this.activePage ) );\n\t\treturn closestBase || $.mobile.path.documentBase.hrefNoHash;\n\t\t}\n\t});\n\n\t// The following handlers should be bound after mobileinit has been triggered\n\t// the following deferred is resolved in the init file\n\t$.mobile.navreadyDeferred = $.Deferred();\n\n\t//these variables make all page containers use the same queue and only navigate one at a time\n\t// queue to hold simultanious page transitions\n\tvar pageTransitionQueue = [],\n\n\t\t// indicates whether or not page is in process of transitioning\n\t\tisPageTransitioning = false;\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n\t\t// resolved on domready\n\tvar domreadyDeferred = $.Deferred(),\n\n\t\t// resolved and nulled on window.load()\n\t\tloadDeferred = $.Deferred(),\n\n\t\t// function that resolves the above deferred\n\t\tpageIsFullyLoaded = function() {\n\n\t\t\t// Resolve and null the deferred\n\t\t\tloadDeferred.resolve();\n\t\t\tloadDeferred = null;\n\t\t},\n\n\t\tdocumentUrl = $.mobile.path.documentUrl,\n\n\t\t// used to track last vclicked element to make sure its value is added to form data\n\t\t$lastVClicked = null;\n\n\t/* Event Bindings - hashchange, submit, and click */\n\tfunction findClosestLink( ele )\t{\n\t\twhile ( ele ) {\n\t\t\t// Look for the closest element with a nodeName of \"a\".\n\t\t\t// Note that we are checking if we have a valid nodeName\n\t\t\t// before attempting to access it. This is because the\n\t\t\t// node we get called with could have originated from within\n\t\t\t// an embedded SVG document where some symbol instance elements\n\t\t\t// don't have nodeName defined on them, or strings are of type\n\t\t\t// SVGAnimatedString.\n\t\t\tif ( ( typeof ele.nodeName === \"string\" ) && ele.nodeName.toLowerCase() === \"a\" ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tele = ele.parentNode;\n\t\t}\n\t\treturn ele;\n\t}\n\n\t$.mobile.loadPage = function( url, opts ) {\n\t\tvar container;\n\n\t\topts = opts || {};\n\t\tcontainer = ( opts.pageContainer || $.mobile.pageContainer );\n\n\t\t// create the deferred that will be supplied to loadPage callers\n\t\t// and resolved by the content widget's load method\n\t\topts.deferred = $.Deferred();\n\n\t\t// Preferring to allow exceptions for uninitialized opts.pageContainer\n\t\t// widgets so we know if we need to force init here for users\n\t\tcontainer.pagecontainer( \"load\", url, opts );\n\n\t\t// provide the deferred\n\t\treturn opts.deferred.promise();\n\t};\n\n\t//define vars for interal use\n\n\t/* internal utility functions */\n\n\t// NOTE Issue #4950 Android phonegap doesn't navigate back properly\n\t//      when a full page refresh has taken place. It appears that hashchange\n\t//      and replacestate history alterations work fine but we need to support\n\t//      both forms of history traversal in our code that uses backward history\n\t//      movement\n\t$.mobile.back = function() {\n\t\tvar nav = window.navigator;\n\n\t\t// if the setting is on and the navigator object is\n\t\t// available use the phonegap navigation capability\n\t\tif ( this.phonegapNavigationEnabled &&\n\t\t\tnav &&\n\t\t\tnav.app &&\n\t\t\tnav.app.backHistory ) {\n\t\t\tnav.app.backHistory();\n\t\t} else {\n\t\t\t$.mobile.pageContainer.pagecontainer( \"back\" );\n\t\t}\n\t};\n\n\t// Direct focus to the page title, or otherwise first focusable element\n\t$.mobile.focusPage = function ( page ) {\n\t\tvar autofocus = page.find( \"[autofocus]\" ),\n\t\t\tpageTitle = page.find( \".ui-title:eq(0)\" );\n\n\t\tif ( autofocus.length ) {\n\t\t\tautofocus.focus();\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pageTitle.length ) {\n\t\t\tpageTitle.focus();\n\t\t} else{\n\t\t\tpage.focus();\n\t\t}\n\t};\n\n\t// No-op implementation of transition degradation\n\t$.mobile._maybeDegradeTransition = $.mobile._maybeDegradeTransition || function( transition ) {\n\t\treturn transition;\n\t};\n\n\t// Exposed $.mobile methods\n\n\t$.mobile.changePage = function( to, options ) {\n\t\t$.mobile.pageContainer.pagecontainer( \"change\", to, options );\n\t};\n\n\t$.mobile.changePage.defaults = {\n\t\ttransition: undefined,\n\t\treverse: false,\n\t\tchangeHash: true,\n\t\tfromHashChange: false,\n\t\trole: undefined, // By default we rely on the role defined by the @data-role attribute.\n\t\tduplicateCachedPage: undefined,\n\t\tpageContainer: undefined,\n\t\tshowLoadMsg: true, //loading message shows by default when pages are being fetched during changePage\n\t\tdataUrl: undefined,\n\t\tfromPage: undefined,\n\t\tallowSamePageTransition: false\n\t};\n\n\t$.mobile._registerInternalEvents = function() {\n\t\tvar getAjaxFormData = function( $form, calculateOnly ) {\n\t\t\tvar url, ret = true, formData, vclickedName, method;\n\t\t\tif ( !$.mobile.ajaxEnabled ||\n\t\t\t\t\t// test that the form is, itself, ajax false\n\t\t\t\t\t$form.is( \":jqmData(ajax='false')\" ) ||\n\t\t\t\t\t// test that $.mobile.ignoreContentEnabled is set and\n\t\t\t\t\t// the form or one of it's parents is ajax=false\n\t\t\t\t\t!$form.jqmHijackable().length ||\n\t\t\t\t\t$form.attr( \"target\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\turl = ( $lastVClicked && $lastVClicked.attr( \"formaction\" ) ) ||\n\t\t\t\t$form.attr( \"action\" );\n\t\t\tmethod = ( $form.attr( \"method\" ) || \"get\" ).toLowerCase();\n\n\t\t\t// If no action is specified, browsers default to using the\n\t\t\t// URL of the document containing the form. Since we dynamically\n\t\t\t// pull in pages from external documents, the form should submit\n\t\t\t// to the URL for the source document of the page containing\n\t\t\t// the form.\n\t\t\tif ( !url ) {\n\t\t\t\t// Get the @data-url for the page containing the form.\n\t\t\t\turl = $.mobile.getClosestBaseUrl( $form );\n\n\t\t\t\t// NOTE: If the method is \"get\", we need to strip off the query string\n\t\t\t\t// because it will get replaced with the new form data. See issue #5710.\n\t\t\t\tif ( method === \"get\" ) {\n\t\t\t\t\turl = $.mobile.path.parseUrl( url ).hrefNoSearch;\n\t\t\t\t}\n\n\t\t\t\tif ( url === $.mobile.path.documentBase.hrefNoHash ) {\n\t\t\t\t\t// The url we got back matches the document base,\n\t\t\t\t\t// which means the page must be an internal/embedded page,\n\t\t\t\t\t// so default to using the actual document url as a browser\n\t\t\t\t\t// would.\n\t\t\t\t\turl = documentUrl.hrefNoSearch;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\turl = $.mobile.path.makeUrlAbsolute(  url, $.mobile.getClosestBaseUrl( $form ) );\n\n\t\t\tif ( ( $.mobile.path.isExternal( url ) && !$.mobile.path.isPermittedCrossDomainRequest( documentUrl, url ) ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( !calculateOnly ) {\n\t\t\t\tformData = $form.serializeArray();\n\n\t\t\t\tif ( $lastVClicked && $lastVClicked[ 0 ].form === $form[ 0 ] ) {\n\t\t\t\t\tvclickedName = $lastVClicked.attr( \"name\" );\n\t\t\t\t\tif ( vclickedName ) {\n\t\t\t\t\t\t// Make sure the last clicked element is included in the form\n\t\t\t\t\t\t$.each( formData, function( key, value ) {\n\t\t\t\t\t\t\tif ( value.name === vclickedName ) {\n\t\t\t\t\t\t\t\t// Unset vclickedName - we've found it in the serialized data already\n\t\t\t\t\t\t\t\tvclickedName = \"\";\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif ( vclickedName ) {\n\t\t\t\t\t\t\tformData.push( { name: vclickedName, value: $lastVClicked.attr( \"value\" ) } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tret = {\n\t\t\t\t\turl: url,\n\t\t\t\t\toptions: {\n\t\t\t\t\t\ttype:\t\tmethod,\n\t\t\t\t\t\tdata:\t\t$.param( formData ),\n\t\t\t\t\t\ttransition:\t$form.jqmData( \"transition\" ),\n\t\t\t\t\t\treverse:\t$form.jqmData( \"direction\" ) === \"reverse\",\n\t\t\t\t\t\treloadPage:\ttrue\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t};\n\n\t\t//bind to form submit events, handle with Ajax\n\t\t$.mobile.document.delegate( \"form\", \"submit\", function( event ) {\n\t\t\tvar formData;\n\n\t\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\t\tformData = getAjaxFormData( $( this ) );\n\t\t\t\tif ( formData ) {\n\t\t\t\t\t$.mobile.changePage( formData.url, formData.options );\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t//add active state on vclick\n\t\t$.mobile.document.bind( \"vclick\", function( event ) {\n\t\t\tvar $btn, btnEls, target = event.target, needClosest = false;\n\t\t\t// if this isn't a left click we don't care. Its important to note\n\t\t\t// that when the virtual event is generated it will create the which attr\n\t\t\tif ( event.which > 1 || !$.mobile.linkBindingEnabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Record that this element was clicked, in case we need it for correct\n\t\t\t// form submission during the \"submit\" handler above\n\t\t\t$lastVClicked = $( target );\n\n\t\t\t// Try to find a target element to which the active class will be applied\n\t\t\tif ( $.data( target, \"mobile-button\" ) ) {\n\t\t\t\t// If the form will not be submitted via AJAX, do not add active class\n\t\t\t\tif ( !getAjaxFormData( $( target ).closest( \"form\" ), true ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// We will apply the active state to this button widget - the parent\n\t\t\t\t// of the input that was clicked will have the associated data\n\t\t\t\tif ( target.parentNode ) {\n\t\t\t\t\ttarget = target.parentNode;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttarget = findClosestLink( target );\n\t\t\t\tif ( !( target && $.mobile.path.parseUrl( target.getAttribute( \"href\" ) || \"#\" ).hash !== \"#\" ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// TODO teach $.mobile.hijackable to operate on raw dom elements so the\n\t\t\t\t// link wrapping can be avoided\n\t\t\t\tif ( !$( target ).jqmHijackable().length ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Avoid calling .closest by using the data set during .buttonMarkup()\n\t\t\t// List items have the button data in the parent of the element clicked\n\t\t\tif ( !!~target.className.indexOf( \"ui-link-inherit\" ) ) {\n\t\t\t\tif ( target.parentNode ) {\n\t\t\t\t\tbtnEls = $.data( target.parentNode, \"buttonElements\" );\n\t\t\t\t}\n\t\t\t// Otherwise, look for the data on the target itself\n\t\t\t} else {\n\t\t\t\tbtnEls = $.data( target, \"buttonElements\" );\n\t\t\t}\n\t\t\t// If found, grab the button's outer element\n\t\t\tif ( btnEls ) {\n\t\t\t\ttarget = btnEls.outer;\n\t\t\t} else {\n\t\t\t\tneedClosest = true;\n\t\t\t}\n\n\t\t\t$btn = $( target );\n\t\t\t// If the outer element wasn't found by the our heuristics, use .closest()\n\t\t\tif ( needClosest ) {\n\t\t\t\t$btn = $btn.closest( \".ui-btn\" );\n\t\t\t}\n\n\t\t\tif ( $btn.length > 0 &&\n\t\t\t\t!( $btn.hasClass( \"ui-state-disabled\" ||\n\n\t\t\t\t\t// DEPRECATED as of 1.4.0 - remove after 1.4.0 release\n\t\t\t\t\t// only ui-state-disabled should be present thereafter\n\t\t\t\t\t$btn.hasClass( \"ui-disabled\" ) ) ) ) {\n\t\t\t\t$.mobile.removeActiveLinkClass( true );\n\t\t\t\t$.mobile.activeClickedLink = $btn;\n\t\t\t\t$.mobile.activeClickedLink.addClass( $.mobile.activeBtnClass );\n\t\t\t}\n\t\t});\n\n\t\t// click routing - direct to HTTP or Ajax, accordingly\n\t\t$.mobile.document.bind( \"click\", function( event ) {\n\t\t\tif ( !$.mobile.linkBindingEnabled || event.isDefaultPrevented() ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar link = findClosestLink( event.target ),\n\t\t\t\t$link = $( link ),\n\n\t\t\t\t//remove active link class if external (then it won't be there if you come back)\n\t\t\t\thttpCleanup = function() {\n\t\t\t\t\twindow.setTimeout(function() { $.mobile.removeActiveLinkClass( true ); }, 200 );\n\t\t\t\t},\n\t\t\t\tbaseUrl, href,\n\t\t\t\tuseDefaultUrlHandling, isExternal,\n\t\t\t\ttransition, reverse, role;\n\n\t\t\t// If a button was clicked, clean up the active class added by vclick above\n\t\t\tif ( $.mobile.activeClickedLink &&\n\t\t\t\t$.mobile.activeClickedLink[ 0 ] === event.target.parentNode ) {\n\t\t\t\thttpCleanup();\n\t\t\t}\n\n\t\t\t// If there is no link associated with the click or its not a left\n\t\t\t// click we want to ignore the click\n\t\t\t// TODO teach $.mobile.hijackable to operate on raw dom elements so the link wrapping\n\t\t\t// can be avoided\n\t\t\tif ( !link || event.which > 1 || !$link.jqmHijackable().length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//if there's a data-rel=back attr, go back in history\n\t\t\tif ( $link.is( \":jqmData(rel='back')\" ) ) {\n\t\t\t\t$.mobile.back();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tbaseUrl = $.mobile.getClosestBaseUrl( $link );\n\n\t\t\t//get href, if defined, otherwise default to empty hash\n\t\t\thref = $.mobile.path.makeUrlAbsolute( $link.attr( \"href\" ) || \"#\", baseUrl );\n\n\t\t\t//if ajax is disabled, exit early\n\t\t\tif ( !$.mobile.ajaxEnabled && !$.mobile.path.isEmbeddedPage( href ) ) {\n\t\t\t\thttpCleanup();\n\t\t\t\t//use default click handling\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// XXX_jblas: Ideally links to application pages should be specified as\n\t\t\t//            an url to the application document with a hash that is either\n\t\t\t//            the site relative path or id to the page. But some of the\n\t\t\t//            internal code that dynamically generates sub-pages for nested\n\t\t\t//            lists and select dialogs, just write a hash in the link they\n\t\t\t//            create. This means the actual URL path is based on whatever\n\t\t\t//            the current value of the base tag is at the time this code\n\t\t\t//            is called.\n\t\t\tif ( href.search( \"#\" ) !== -1 &&\n\t\t\t\t!( $.mobile.path.isExternal( href ) && $.mobile.path.isAbsoluteUrl( href ) ) ) {\n\n\t\t\t\thref = href.replace( /[^#]*#/, \"\" );\n\t\t\t\tif ( !href ) {\n\t\t\t\t\t//link was an empty hash meant purely\n\t\t\t\t\t//for interaction, so we ignore it.\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t} else if ( $.mobile.path.isPath( href ) ) {\n\t\t\t\t\t//we have apath so make it the href we want to load.\n\t\t\t\t\thref = $.mobile.path.makeUrlAbsolute( href, baseUrl );\n\t\t\t\t} else {\n\t\t\t\t\t//we have a simple id so use the documentUrl as its base.\n\t\t\t\t\thref = $.mobile.path.makeUrlAbsolute( \"#\" + href, documentUrl.hrefNoHash );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Should we handle this link, or let the browser deal with it?\n\t\t\tuseDefaultUrlHandling = $link.is( \"[rel='external']\" ) || $link.is( \":jqmData(ajax='false')\" ) || $link.is( \"[target]\" );\n\n\t\t\t// Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR\n\t\t\t// requests if the document doing the request was loaded via the file:// protocol.\n\t\t\t// This is usually to allow the application to \"phone home\" and fetch app specific\n\t\t\t// data. We normally let the browser handle external/cross-domain urls, but if the\n\t\t\t// allowCrossDomainPages option is true, we will allow cross-domain http/https\n\t\t\t// requests to go through our page loading logic.\n\n\t\t\t//check for protocol or rel and its not an embedded page\n\t\t\t//TODO overlap in logic from isExternal, rel=external check should be\n\t\t\t//     moved into more comprehensive isExternalLink\n\t\t\tisExternal = useDefaultUrlHandling || ( $.mobile.path.isExternal( href ) && !$.mobile.path.isPermittedCrossDomainRequest( documentUrl, href ) );\n\n\t\t\tif ( isExternal ) {\n\t\t\t\thttpCleanup();\n\t\t\t\t//use default click handling\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//use ajax\n\t\t\ttransition = $link.jqmData( \"transition\" );\n\t\t\treverse = $link.jqmData( \"direction\" ) === \"reverse\" ||\n\t\t\t\t\t\t// deprecated - remove by 1.0\n\t\t\t\t\t\t$link.jqmData( \"back\" );\n\n\t\t\t//this may need to be more specific as we use data-rel more\n\t\t\trole = $link.attr( \"data-\" + $.mobile.ns + \"rel\" ) || undefined;\n\n\t\t\t$.mobile.changePage( href, { transition: transition, reverse: reverse, role: role, link: $link } );\n\t\t\tevent.preventDefault();\n\t\t});\n\n\t\t//prefetch pages when anchors with data-prefetch are encountered\n\t\t$.mobile.document.delegate( \".ui-page\", \"pageshow.prefetch\", function() {\n\t\t\tvar urls = [];\n\t\t\t$( this ).find( \"a:jqmData(prefetch)\" ).each(function() {\n\t\t\t\tvar $link = $( this ),\n\t\t\t\t\turl = $link.attr( \"href\" );\n\n\t\t\t\tif ( url && $.inArray( url, urls ) === -1 ) {\n\t\t\t\t\turls.push( url );\n\n\t\t\t\t\t$.mobile.loadPage( url, { role: $link.attr( \"data-\" + $.mobile.ns + \"rel\" ),prefetch: true } );\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\t// TODO ensure that the navigate binding in the content widget happens at the right time\n\t\t$.mobile.pageContainer.pagecontainer();\n\n\t\t//set page min-heights to be device specific\n\t\t$.mobile.document.bind( \"pageshow\", function() {\n\n\t\t\t// We need to wait for window.load to make sure that styles have already been rendered,\n\t\t\t// otherwise heights of external toolbars will have the wrong value\n\t\t\tif ( loadDeferred ) {\n\t\t\t\tloadDeferred.done( $.mobile.resetActivePageHeight );\n\t\t\t} else {\n\t\t\t\t$.mobile.resetActivePageHeight();\n\t\t\t}\n\t\t});\n\t\t$.mobile.window.bind( \"throttledresize\", $.mobile.resetActivePageHeight );\n\n\t};//navreadyDeferred done callback\n\n\t$( function() { domreadyDeferred.resolve(); } );\n\n\t// Account for the possibility that the load event has already fired\n\tif ( document.readyState === \"complete\" ) {\n\t\tpageIsFullyLoaded();\n\t} else {\n\t\t$.mobile.window.load( pageIsFullyLoaded );\n\t}\n\n\t$.when( domreadyDeferred, $.mobile.navreadyDeferred ).done( function() { $.mobile._registerInternalEvents(); } );\n})( jQuery );\n\n\n(function( $, window, undefined ) {\n\n\t// TODO remove direct references to $.mobile and properties, we should\n\t//      favor injection with params to the constructor\n\t$.mobile.Transition = function() {\n\t\tthis.init.apply( this, arguments );\n\t};\n\n\t$.extend($.mobile.Transition.prototype, {\n\t\ttoPreClass: \" ui-page-pre-in\",\n\n\t\tinit: function( name, reverse, $to, $from ) {\n\t\t\t$.extend(this, {\n\t\t\t\tname: name,\n\t\t\t\treverse: reverse,\n\t\t\t\t$to: $to,\n\t\t\t\t$from: $from,\n\t\t\t\tdeferred: new $.Deferred()\n\t\t\t});\n\t\t},\n\n\t\tcleanFrom: function() {\n\t\t\tthis.$from\n\t\t\t\t.removeClass( $.mobile.activePageClass + \" out in reverse \" + this.name )\n\t\t\t\t.height( \"\" );\n\t\t},\n\n\t\t// NOTE overridden by child object prototypes, noop'd here as defaults\n\t\tbeforeDoneIn: function() {},\n\t\tbeforeDoneOut: function() {},\n\t\tbeforeStartOut: function() {},\n\n\t\tdoneIn: function() {\n\t\t\tthis.beforeDoneIn();\n\n\t\t\tthis.$to.removeClass( \"out in reverse \" + this.name ).height( \"\" );\n\n\t\t\tthis.toggleViewportClass();\n\n\t\t\t// In some browsers (iOS5), 3D transitions block the ability to scroll to the desired location during transition\n\t\t\t// This ensures we jump to that spot after the fact, if we aren't there already.\n\t\t\tif ( $.mobile.window.scrollTop() !== this.toScroll ) {\n\t\t\t\tthis.scrollPage();\n\t\t\t}\n\t\t\tif ( !this.sequential ) {\n\t\t\t\tthis.$to.addClass( $.mobile.activePageClass );\n\t\t\t}\n\t\t\tthis.deferred.resolve( this.name, this.reverse, this.$to, this.$from, true );\n\t\t},\n\n\t\tdoneOut: function( screenHeight, reverseClass, none, preventFocus ) {\n\t\t\tthis.beforeDoneOut();\n\t\t\tthis.startIn( screenHeight, reverseClass, none, preventFocus );\n\t\t},\n\n\t\thideIn: function( callback ) {\n\t\t\t// Prevent flickering in phonegap container: see comments at #4024 regarding iOS\n\t\t\tthis.$to.css( \"z-index\", -10 );\n\t\t\tcallback.call( this );\n\t\t\tthis.$to.css( \"z-index\", \"\" );\n\t\t},\n\n\t\tscrollPage: function() {\n\t\t\t// By using scrollTo instead of silentScroll, we can keep things better in order\n\t\t\t// Just to be precautios, disable scrollstart listening like silentScroll would\n\t\t\t$.event.special.scrollstart.enabled = false;\n\t\t\t//if we are hiding the url bar or the page was previously scrolled scroll to hide or return to position\n\t\t\tif ( $.mobile.hideUrlBar || this.toScroll !== $.mobile.defaultHomeScroll ) {\n\t\t\t\twindow.scrollTo( 0, this.toScroll );\n\t\t\t}\n\n\t\t\t// reenable scrollstart listening like silentScroll would\n\t\t\tsetTimeout( function() {\n\t\t\t\t$.event.special.scrollstart.enabled = true;\n\t\t\t}, 150 );\n\t\t},\n\n\t\tstartIn: function( screenHeight, reverseClass, none, preventFocus ) {\n\t\t\tthis.hideIn(function() {\n\t\t\t\tthis.$to.addClass( $.mobile.activePageClass + this.toPreClass );\n\n\t\t\t\t// Send focus to page as it is now display: block\n\t\t\t\tif ( !preventFocus ) {\n\t\t\t\t\t$.mobile.focusPage( this.$to );\n\t\t\t\t}\n\n\t\t\t\t// Set to page height\n\t\t\t\tthis.$to.height( screenHeight + this.toScroll );\n\n                if ( !none ) {\n                    this.scrollPage();\n                }\n\t\t\t});\n\n\t\t\tthis.$to\n\t\t\t\t.removeClass( this.toPreClass )\n\t\t\t\t.addClass( this.name + \" in \" + reverseClass );\n\n\t\t\tif ( !none ) {\n\t\t\t\tthis.$to.animationComplete( $.proxy(function() {\n\t\t\t\t\tthis.doneIn();\n\t\t\t\t}, this ));\n\t\t\t} else {\n\t\t\t\tthis.doneIn();\n\t\t\t}\n\n\t\t},\n\n\t\tstartOut: function( screenHeight, reverseClass, none ) {\n\t\t\tthis.beforeStartOut( screenHeight, reverseClass, none );\n\n\t\t\t// Set the from page's height and start it transitioning out\n\t\t\t// Note: setting an explicit height helps eliminate tiling in the transitions\n\t\t\tthis.$from\n\t\t\t\t.height( screenHeight + $.mobile.window.scrollTop() )\n\t\t\t\t.addClass( this.name + \" out\" + reverseClass );\n\t\t},\n\n\t\ttoggleViewportClass: function() {\n\t\t\t$.mobile.pageContainer.toggleClass( \"ui-mobile-viewport-transitioning viewport-\" + this.name );\n\t\t},\n\n\t\ttransition: function() {\n\t\t\t// NOTE many of these could be calculated/recorded in the constructor, it's my\n\t\t\t//      opinion that binding them as late as possible has value with regards to\n\t\t\t//      better transitions with fewer bugs. Ie, it's not guaranteed that the\n\t\t\t//      object will be created and transition will be run immediately after as\n\t\t\t//      it is today. So we wait until transition is invoked to gather the following\n\t\t\tvar none,\n\t\t\t\treverseClass = this.reverse ? \" reverse\" : \"\",\n\t\t\t\tscreenHeight = $.mobile.getScreenHeight(),\n\t\t\t\tmaxTransitionOverride = $.mobile.maxTransitionWidth !== false &&\n\t\t\t\t\t$.mobile.window.width() > $.mobile.maxTransitionWidth;\n\n\t\t\tthis.toScroll = $.mobile.navigate.history.getActive().lastScroll || $.mobile.defaultHomeScroll;\n\n\t\t\tnone = !$.support.cssTransitions || !$.support.cssAnimations ||\n\t\t\t\tmaxTransitionOverride || !this.name || this.name === \"none\" ||\n\t\t\t\tMath.max( $.mobile.window.scrollTop(), this.toScroll ) >\n\t\t\t\t\t$.mobile.getMaxScrollForTransition();\n\n\t\t\tthis.toggleViewportClass();\n\n\t\t\tif ( this.$from && !none ) {\n\t\t\t\tthis.startOut( screenHeight, reverseClass, none );\n\t\t\t} else {\n\t\t\t\tthis.doneOut( screenHeight, reverseClass, none, true );\n\t\t\t}\n\n\t\t\treturn this.deferred.promise();\n\t\t}\n\t});\n})( jQuery, this );\n\n\n(function( $ ) {\n\n\t$.mobile.SerialTransition = function() {\n\t\tthis.init.apply(this, arguments);\n\t};\n\n\t$.extend($.mobile.SerialTransition.prototype, $.mobile.Transition.prototype, {\n\t\tsequential: true,\n\n\t\tbeforeDoneOut: function() {\n\t\t\tif ( this.$from ) {\n\t\t\t\tthis.cleanFrom();\n\t\t\t}\n\t\t},\n\n\t\tbeforeStartOut: function( screenHeight, reverseClass, none ) {\n\t\t\tthis.$from.animationComplete($.proxy(function() {\n\t\t\t\tthis.doneOut( screenHeight, reverseClass, none );\n\t\t\t}, this ));\n\t\t}\n\t});\n\n})( jQuery );\n\n\n(function( $ ) {\n\n\t$.mobile.ConcurrentTransition = function() {\n\t\tthis.init.apply(this, arguments);\n\t};\n\n\t$.extend($.mobile.ConcurrentTransition.prototype, $.mobile.Transition.prototype, {\n\t\tsequential: false,\n\n\t\tbeforeDoneIn: function() {\n\t\t\tif ( this.$from ) {\n\t\t\t\tthis.cleanFrom();\n\t\t\t}\n\t\t},\n\n\t\tbeforeStartOut: function( screenHeight, reverseClass, none ) {\n\t\t\tthis.doneOut( screenHeight, reverseClass, none );\n\t\t}\n\t});\n\n})( jQuery );\n\n\n(function( $ ) {\n\n\t// generate the handlers from the above\n\tvar defaultGetMaxScrollForTransition = function() {\n\t\treturn $.mobile.getScreenHeight() * 3;\n\t};\n\n\t//transition handler dictionary for 3rd party transitions\n\t$.mobile.transitionHandlers = {\n\t\t\"sequential\": $.mobile.SerialTransition,\n\t\t\"simultaneous\": $.mobile.ConcurrentTransition\n\t};\n\n\t// Make our transition handler the public default.\n\t$.mobile.defaultTransitionHandler = $.mobile.transitionHandlers.sequential;\n\n\t$.mobile.transitionFallbacks = {};\n\n\t// If transition is defined, check if css 3D transforms are supported, and if not, if a fallback is specified\n\t$.mobile._maybeDegradeTransition = function( transition ) {\n\t\tif ( transition && !$.support.cssTransform3d && $.mobile.transitionFallbacks[ transition ] ) {\n\t\t\ttransition = $.mobile.transitionFallbacks[ transition ];\n\t\t}\n\n\t\treturn transition;\n\t};\n\n\t// Set the getMaxScrollForTransition to default if no implementation was set by user\n\t$.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defaultGetMaxScrollForTransition;\n\n})( jQuery );\n\n/*\n* fallback transition for flip in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.flip = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for flow in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.flow = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for pop in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.pop = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for slide in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n// Use the simultaneous transitions handler for slide transitions\n$.mobile.transitionHandlers.slide = $.mobile.transitionHandlers.simultaneous;\n\n// Set the slide transitions's fallback to \"fade\"\n$.mobile.transitionFallbacks.slide = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for slidedown in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.slidedown = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for slidefade in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n// Set the slide transitions's fallback to \"fade\"\n$.mobile.transitionFallbacks.slidefade = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for slideup in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.slideup = \"fade\";\n\n})( jQuery, this );\n\n/*\n* fallback transition for turn in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n*/\n\n(function( $, window, undefined ) {\n\n$.mobile.transitionFallbacks.turn = \"fade\";\n\n})( jQuery, this );\n\n\n(function( $, undefined ) {\n\n$.mobile.degradeInputs = {\n\tcolor: false,\n\tdate: false,\n\tdatetime: false,\n\t\"datetime-local\": false,\n\temail: false,\n\tmonth: false,\n\tnumber: false,\n\trange: \"number\",\n\tsearch: \"text\",\n\ttel: false,\n\ttime: false,\n\turl: false,\n\tweek: false\n};\n// Backcompat remove in 1.5\n$.mobile.page.prototype.options.degradeInputs = $.mobile.degradeInputs;\n\n// Auto self-init widgets\n$.mobile.degradeInputsWithin = function( target ) {\n\n\ttarget = $( target );\n\n\t// Degrade inputs to avoid poorly implemented native functionality\n\ttarget.find( \"input\" ).not( $.mobile.page.prototype.keepNativeSelector() ).each(function() {\n\t\tvar element = $( this ),\n\t\t\ttype = this.getAttribute( \"type\" ),\n\t\t\toptType = $.mobile.degradeInputs[ type ] || \"text\",\n\t\t\thtml, hasType, findstr, repstr;\n\n\t\tif ( $.mobile.degradeInputs[ type ] ) {\n\t\t\thtml = $( \"<div>\" ).html( element.clone() ).html();\n\t\t\t// In IE browsers, the type sometimes doesn't exist in the cloned markup, so we replace the closing tag instead\n\t\t\thasType = html.indexOf( \" type=\" ) > -1;\n\t\t\tfindstr = hasType ? /\\s+type=[\"']?\\w+['\"]?/ : /\\/?>/;\n\t\t\trepstr = \" type=\\\"\" + optType + \"\\\" data-\" + $.mobile.ns + \"type=\\\"\" + type + \"\\\"\" + ( hasType ? \"\" : \">\" );\n\n\t\t\telement.replaceWith( html.replace( findstr, repstr ) );\n\t\t}\n\t});\n\n};\n\n})( jQuery );\n\n(function( $, window, undefined ) {\n\n$.widget( \"mobile.page\", $.mobile.page, {\n\toptions: {\n\n\t\t// Accepts left, right and none\n\t\tcloseBtn: \"left\",\n\t\tcloseBtnText: \"Close\",\n\t\toverlayTheme: \"a\",\n\t\tcorners: true,\n\t\tdialog: false\n\t},\n\n\t_create: function() {\n\t\tthis._super();\n\t\tif ( this.options.dialog ) {\n\n\t\t\t$.extend( this, {\n\t\t\t\t_inner: this.element.children(),\n\t\t\t\t_headerCloseButton: null\n\t\t\t});\n\n\t\t\tif ( !this.options.enhanced ) {\n\t\t\t\tthis._setCloseBtn( this.options.closeBtn );\n\t\t\t}\n\t\t}\n\t},\n\n\t_enhance: function() {\n\t\tthis._super();\n\n\t\t// Class the markup for dialog styling and wrap interior\n\t\tif ( this.options.dialog ) {\n\t\t\tthis.element.addClass( \"ui-dialog\" )\n\t\t\t\t.wrapInner( $( \"<div/>\", {\n\n\t\t\t\t\t// ARIA role\n\t\t\t\t\t\"role\" : \"dialog\",\n\t\t\t\t\t\"class\" : \"ui-dialog-contain ui-overlay-shadow\" +\n\t\t\t\t\t\t( this.options.corners ? \" ui-corner-all\" : \"\" )\n\t\t\t\t}));\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar closeButtonLocation, closeButtonText,\n\t\t\tcurrentOpts = this.options;\n\n\t\tif ( options.corners !== undefined ) {\n\t\t\tthis._inner.toggleClass( \"ui-corner-all\", !!options.corners );\n\t\t}\n\n\t\tif ( options.overlayTheme !== undefined ) {\n\t\t\tif ( $.mobile.activePage[ 0 ] === this.element[ 0 ] ) {\n\t\t\t\tcurrentOpts.overlayTheme = options.overlayTheme;\n\t\t\t\tthis._handlePageBeforeShow();\n\t\t\t}\n\t\t}\n\n\t\tif ( options.closeBtnText !== undefined ) {\n\t\t\tcloseButtonLocation = currentOpts.closeBtn;\n\t\t\tcloseButtonText = options.closeBtnText;\n\t\t}\n\n\t\tif ( options.closeBtn !== undefined ) {\n\t\t\tcloseButtonLocation = options.closeBtn;\n\t\t}\n\n\t\tif ( closeButtonLocation ) {\n\t\t\tthis._setCloseBtn( closeButtonLocation, closeButtonText );\n\t\t}\n\n\t\tthis._super( options );\n\t},\n\n\t_handlePageBeforeShow: function () {\n\t\tif ( this.options.overlayTheme && this.options.dialog ) {\n\t\t\tthis.removeContainerBackground();\n\t\t\tthis.setContainerBackground( this.options.overlayTheme );\n\t\t} else {\n\t\t\tthis._super();\n\t\t}\n\t},\n\n\t_setCloseBtn: function( location, text ) {\n\t\tvar dst,\n\t\t\tbtn = this._headerCloseButton;\n\n\t\t// Sanitize value\n\t\tlocation = \"left\" === location ? \"left\" : \"right\" === location ? \"right\" : \"none\";\n\n\t\tif ( \"none\" === location ) {\n\t\t\tif ( btn ) {\n\t\t\t\tbtn.remove();\n\t\t\t\tbtn = null;\n\t\t\t}\n\t\t} else if ( btn ) {\n\t\t\tbtn.removeClass( \"ui-btn-left ui-btn-right\" ).addClass( \"ui-btn-\" + location );\n\t\t\tif ( text ) {\n\t\t\t\tbtn.text( text );\n\t\t\t}\n\t\t} else {\n\t\t\tdst = this._inner.find( \":jqmData(role='header')\" ).first();\n\t\t\tbtn = $( \"<a></a>\", {\n\t\t\t\t\t\"href\": \"#\",\n\t\t\t\t\t\"class\": \"ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-\" + location\n\t\t\t\t})\n\t\t\t\t.attr( \"data-\" + $.mobile.ns + \"rel\", \"back\" )\n\t\t\t\t.text( text || this.options.closeBtnText || \"\" )\n\t\t\t\t.prependTo( dst );\n\t\t}\n\n\t\tthis._headerCloseButton = btn;\n\t}\n});\n\n})( jQuery, this );\n\n(function( $, window, undefined ) {\n\n$.widget( \"mobile.dialog\", {\n\toptions: {\n\n\t\t// Accepts left, right and none\n\t\tcloseBtn: \"left\",\n\t\tcloseBtnText: \"Close\",\n\t\toverlayTheme: \"a\",\n\t\tcorners: true\n\t},\n\n\t// Override the theme set by the page plugin on pageshow\n\t_handlePageBeforeShow: function() {\n\t\tthis._isCloseable = true;\n\t\tif ( this.options.overlayTheme ) {\n\t\t\tthis.element\n\t\t\t\t.page( \"removeContainerBackground\" )\n\t\t\t\t.page( \"setContainerBackground\", this.options.overlayTheme );\n\t\t}\n\t},\n\n\t_handlePageBeforeHide: function() {\n\t\tthis._isCloseable = false;\n\t},\n\n\t// click and submit events:\n\t// - clicks and submits should use the closing transition that the dialog\n\t//   opened with unless a data-transition is specified on the link/form\n\t// - if the click was on the close button, or the link has a data-rel=\"back\"\n\t//   it'll go back in history naturally\n\t_handleVClickSubmit: function( event ) {\n\t\tvar attrs,\n\t\t\t$target = $( event.target ).closest( event.type === \"vclick\" ? \"a\" : \"form\" );\n\n\t\tif ( $target.length && !$target.jqmData( \"transition\" ) ) {\n\t\t\tattrs = {};\n\t\t\tattrs[ \"data-\" + $.mobile.ns + \"transition\" ] =\n\t\t\t\t( $.mobile.navigate.history.getActive() || {} )[ \"transition\" ] ||\n\t\t\t\t$.mobile.defaultDialogTransition;\n\t\t\tattrs[ \"data-\" + $.mobile.ns + \"direction\" ] = \"reverse\";\n\t\t\t$target.attr( attrs );\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tvar elem = this.element,\n\t\t\topts = this.options;\n\n\t\t// Class the markup for dialog styling and wrap interior\n\t\telem.addClass( \"ui-dialog\" )\n\t\t\t.wrapInner( $( \"<div/>\", {\n\n\t\t\t\t// ARIA role\n\t\t\t\t\"role\" : \"dialog\",\n\t\t\t\t\"class\" : \"ui-dialog-contain ui-overlay-shadow\" +\n\t\t\t\t\t( !!opts.corners ? \" ui-corner-all\" : \"\" )\n\t\t\t}));\n\n\t\t$.extend( this, {\n\t\t\t_isCloseable: false,\n\t\t\t_inner: elem.children(),\n\t\t\t_headerCloseButton: null\n\t\t});\n\n\t\tthis._on( elem, {\n\t\t\tvclick: \"_handleVClickSubmit\",\n\t\t\tsubmit: \"_handleVClickSubmit\",\n\t\t\tpagebeforeshow: \"_handlePageBeforeShow\",\n\t\t\tpagebeforehide: \"_handlePageBeforeHide\"\n\t\t});\n\n\t\tthis._setCloseBtn( opts.closeBtn );\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar closeButtonLocation, closeButtonText,\n\t\t\tcurrentOpts = this.options;\n\n\t\tif ( options.corners !== undefined ) {\n\t\t\tthis._inner.toggleClass( \"ui-corner-all\", !!options.corners );\n\t\t}\n\n\t\tif ( options.overlayTheme !== undefined ) {\n\t\t\tif ( $.mobile.activePage[ 0 ] === this.element[ 0 ] ) {\n\t\t\t\tcurrentOpts.overlayTheme = options.overlayTheme;\n\t\t\t\tthis._handlePageBeforeShow();\n\t\t\t}\n\t\t}\n\n\t\tif ( options.closeBtnText !== undefined ) {\n\t\t\tcloseButtonLocation = currentOpts.closeBtn;\n\t\t\tcloseButtonText = options.closeBtnText;\n\t\t}\n\n\t\tif ( options.closeBtn !== undefined ) {\n\t\t\tcloseButtonLocation = options.closeBtn;\n\t\t}\n\n\t\tif ( closeButtonLocation ) {\n\t\t\tthis._setCloseBtn( closeButtonLocation, closeButtonText );\n\t\t}\n\n\t\tthis._super( options );\n\t},\n\n\t_setCloseBtn: function( location, text ) {\n\t\tvar dst,\n\t\t\tbtn = this._headerCloseButton;\n\n\t\t// Sanitize value\n\t\tlocation = \"left\" === location ? \"left\" : \"right\" === location ? \"right\" : \"none\";\n\n\t\tif ( \"none\" === location ) {\n\t\t\tif ( btn ) {\n\t\t\t\tbtn.remove();\n\t\t\t\tbtn = null;\n\t\t\t}\n\t\t} else if ( btn ) {\n\t\t\tbtn.removeClass( \"ui-btn-left ui-btn-right\" ).addClass( \"ui-btn-\" + location );\n\t\t\tif ( text ) {\n\t\t\t\tbtn.text( text );\n\t\t\t}\n\t\t} else {\n\t\t\tdst = this._inner.find( \":jqmData(role='header')\" ).first();\n\t\t\tbtn = $( \"<a></a>\", {\n\t\t\t\t\t\"role\": \"button\",\n\t\t\t\t\t\"href\": \"#\",\n\t\t\t\t\t\"class\": \"ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-\" + location\n\t\t\t\t})\n\t\t\t\t.text( text || this.options.closeBtnText || \"\" )\n\t\t\t\t.prependTo( dst );\n\t\t\tthis._on( btn, { click: \"close\" } );\n\t\t}\n\n\t\tthis._headerCloseButton = btn;\n\t},\n\n\t// Close method goes back in history\n\tclose: function() {\n\t\tvar hist = $.mobile.navigate.history;\n\n\t\tif ( this._isCloseable ) {\n\t\t\tthis._isCloseable = false;\n\t\t\t// If the hash listening is enabled and there is at least one preceding history\n\t\t\t// entry it's ok to go back. Initial pages with the dialog hash state are an example\n\t\t\t// where the stack check is necessary\n\t\t\tif ( $.mobile.hashListeningEnabled && hist.activeIndex > 0 ) {\n\t\t\t\t$.mobile.back();\n\t\t\t} else {\n\t\t\t\t$.mobile.pageContainer.pagecontainer( \"back\" );\n\t\t\t}\n\t\t}\n\t}\n});\n\n})( jQuery, this );\n\n(function( $, undefined ) {\n\nvar rInitialLetter = /([A-Z])/g,\n\n\t// Construct iconpos class from iconpos value\n\ticonposClass = function( iconpos ) {\n\t\treturn ( \"ui-btn-icon-\" + ( iconpos === null ? \"left\" : iconpos ) );\n\t};\n\n$.widget( \"mobile.collapsible\", {\n\toptions: {\n\t\tenhanced: false,\n\t\texpandCueText: null,\n\t\tcollapseCueText: null,\n\t\tcollapsed: true,\n\t\theading: \"h1,h2,h3,h4,h5,h6,legend\",\n\t\tcollapsedIcon: null,\n\t\texpandedIcon: null,\n\t\ticonpos: null,\n\t\ttheme: null,\n\t\tcontentTheme: null,\n\t\tinset: null,\n\t\tcorners: null,\n\t\tmini: null\n\t},\n\n\t_create: function() {\n\t\tvar elem = this.element,\n\t\t\tui = {\n\t\t\t\taccordion: elem\n\t\t\t\t\t.closest( \":jqmData(role='collapsible-set'),\" +\n\t\t\t\t\t\t\":jqmData(role='collapsibleset')\" +\n\t\t\t\t\t\t( $.mobile.collapsibleset ? \", :mobile-collapsibleset\" :\n\t\t\t\t\t\t\t\"\" ) )\n\t\t\t\t\t.addClass( \"ui-collapsible-set\" )\n\t\t\t};\n\n\t\tthis._ui = ui;\n\t\tthis._renderedOptions = this._getOptions( this.options );\n\n\t\tif ( this.options.enhanced ) {\n\t\t\tui.heading = this.element.children( \".ui-collapsible-heading\" );\n\t\t\tui.content = ui.heading.next();\n\t\t\tui.anchor = ui.heading.children();\n\t\t\tui.status = ui.anchor.children( \".ui-collapsible-heading-status\" );\n\t\t} else {\n\t\t\tthis._enhance( elem, ui );\n\t\t}\n\n\t\tthis._on( ui.heading, {\n\t\t\t\"tap\": function() {\n\t\t\t\tui.heading.find( \"a\" ).first().addClass( $.mobile.activeBtnClass );\n\t\t\t},\n\n\t\t\t\"click\": function( event ) {\n\t\t\t\tthis._handleExpandCollapse( !ui.heading.hasClass( \"ui-collapsible-heading-collapsed\" ) );\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}\n\t\t});\n\t},\n\n\t// Adjust the keys inside options for inherited values\n\t_getOptions: function( options ) {\n\t\tvar key,\n\t\t\taccordion = this._ui.accordion,\n\t\t\taccordionWidget = this._ui.accordionWidget;\n\n\t\t// Copy options\n\t\toptions = $.extend( {}, options );\n\n\t\tif ( accordion.length && !accordionWidget ) {\n\t\t\tthis._ui.accordionWidget =\n\t\t\taccordionWidget = accordion.data( \"mobile-collapsibleset\" );\n\t\t}\n\n\t\tfor ( key in options ) {\n\n\t\t\t// Retrieve the option value first from the options object passed in and, if\n\t\t\t// null, from the parent accordion or, if that's null too, or if there's no\n\t\t\t// parent accordion, then from the defaults.\n\t\t\toptions[ key ] =\n\t\t\t\t( options[ key ] != null ) ? options[ key ] :\n\t\t\t\t( accordionWidget ) ? accordionWidget.options[ key ] :\n\t\t\t\taccordion.length ? $.mobile.getAttribute( accordion[ 0 ],\n\t\t\t\t\tkey.replace( rInitialLetter, \"-$1\" ).toLowerCase() ):\n\t\t\t\tnull;\n\n\t\t\tif ( null == options[ key ] ) {\n\t\t\t\toptions[ key ] = $.mobile.collapsible.defaults[ key ];\n\t\t\t}\n\t\t}\n\n\t\treturn options;\n\t},\n\n\t_themeClassFromOption: function( prefix, value ) {\n\t\treturn ( value ? ( value === \"none\" ? \"\" : prefix + value ) : \"\" );\n\t},\n\n\t_enhance: function( elem, ui ) {\n\t\tvar iconclass,\n\t\t\topts = this._renderedOptions,\n\t\t\tcontentThemeClass = this._themeClassFromOption( \"ui-body-\", opts.contentTheme );\n\n\t\telem.addClass( \"ui-collapsible \" +\n\t\t\t( opts.inset ? \"ui-collapsible-inset \" : \"\" ) +\n\t\t\t( opts.inset && opts.corners ? \"ui-corner-all \" : \"\" ) +\n\t\t\t( contentThemeClass ? \"ui-collapsible-themed-content \" : \"\" ) );\n\t\tui.originalHeading = elem.children( this.options.heading ).first(),\n\t\tui.content = elem\n\t\t\t.wrapInner( \"<div \" +\n\t\t\t\t\"class='ui-collapsible-content \" +\n\t\t\t\tcontentThemeClass + \"'></div>\" )\n\t\t\t.children( \".ui-collapsible-content\" ),\n\t\tui.heading = ui.originalHeading;\n\n\t\t// Replace collapsibleHeading if it's a legend\n\t\tif ( ui.heading.is( \"legend\" ) ) {\n\t\t\tui.heading = $( \"<div role='heading'>\"+ ui.heading.html() +\"</div>\" );\n\t\t\tui.placeholder = $( \"<div><!-- placeholder for legend --></div>\" ).insertBefore( ui.originalHeading );\n\t\t\tui.originalHeading.remove();\n\t\t}\n\n\t\ticonclass = ( opts.collapsed ? ( opts.collapsedIcon ? \"ui-icon-\" + opts.collapsedIcon : \"\" ):\n\t\t\t( opts.expandedIcon ? \"ui-icon-\" + opts.expandedIcon : \"\" ) );\n\n\t\tui.status = $( \"<span class='ui-collapsible-heading-status'></span>\" );\n\t\tui.anchor = ui.heading\n\t\t\t.detach()\n\t\t\t//modify markup & attributes\n\t\t\t.addClass( \"ui-collapsible-heading\" )\n\t\t\t.append( ui.status )\n\t\t\t.wrapInner( \"<a href='#' class='ui-collapsible-heading-toggle'></a>\" )\n\t\t\t.find( \"a\" )\n\t\t\t\t.first()\n\t\t\t\t.addClass( \"ui-btn \" +\n\t\t\t\t\t( iconclass ? iconclass + \" \" : \"\" ) +\n\t\t\t\t\t( iconclass ? iconposClass( opts.iconpos ) +\n\t\t\t\t\t\t\" \" : \"\" ) +\n\t\t\t\t\tthis._themeClassFromOption( \"ui-btn-\", opts.theme ) + \" \" +\n\t\t\t\t\t( opts.mini ? \"ui-mini \" : \"\" ) );\n\n\t\t//drop heading in before content\n\t\tui.heading.insertBefore( ui.content );\n\n\t\tthis._handleExpandCollapse( this.options.collapsed );\n\n\t\treturn ui;\n\t},\n\n\trefresh: function() {\n\t\tthis._applyOptions( this.options );\n\t\tthis._renderedOptions = this._getOptions( this.options );\n\t},\n\n\t_applyOptions: function( options ) {\n\t\tvar isCollapsed, newTheme, oldTheme, hasCorners, hasIcon,\n\t\t\telem = this.element,\n\t\t\tcurrentOpts = this._renderedOptions,\n\t\t\tui = this._ui,\n\t\t\tanchor = ui.anchor,\n\t\t\tstatus = ui.status,\n\t\t\topts = this._getOptions( options );\n\n\t\t// First and foremost we need to make sure the collapsible is in the proper\n\t\t// state, in case somebody decided to change the collapsed option at the\n\t\t// same time as another option\n\t\tif ( options.collapsed !== undefined ) {\n\t\t\tthis._handleExpandCollapse( options.collapsed );\n\t\t}\n\n\t\tisCollapsed = elem.hasClass( \"ui-collapsible-collapsed\" );\n\n\t\t// We only need to apply the cue text for the current state right away.\n\t\t// The cue text for the alternate state will be stored in the options\n\t\t// and applied the next time the collapsible's state is toggled\n\t\tif ( isCollapsed ) {\n\t\t\tif ( opts.expandCueText !== undefined ) {\n\t\t\t\tstatus.text( opts.expandCueText );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( opts.collapseCueText !== undefined ) {\n\t\t\t\tstatus.text( opts.collapseCueText );\n\t\t\t}\n\t\t}\n\n\t\t// Update icon\n\n\t\t// Is it supposed to have an icon?\n\t\thasIcon =\n\n\t\t\t// If the collapsedIcon is being set, consult that\n\t\t\t( opts.collapsedIcon !== undefined ? opts.collapsedIcon !== false :\n\n\t\t\t\t// Otherwise consult the existing option value\n\t\t\t\tcurrentOpts.collapsedIcon !== false );\n\n\n\t\t// If any icon-related options have changed, make sure the new icon\n\t\t// state is reflected by first removing all icon-related classes\n\t\t// reflecting the current state and then adding all icon-related\n\t\t// classes for the new state\n\t\tif ( !( opts.iconpos === undefined &&\n\t\t\topts.collapsedIcon === undefined &&\n\t\t\topts.expandedIcon === undefined ) ) {\n\n\t\t\t// Remove all current icon-related classes\n\t\t\tanchor.removeClass( [ iconposClass( currentOpts.iconpos ) ]\n\t\t\t\t.concat( ( currentOpts.expandedIcon ?\n\t\t\t\t\t[ \"ui-icon-\" + currentOpts.expandedIcon ] : [] ) )\n\t\t\t\t.concat( ( currentOpts.collapsedIcon ?\n\t\t\t\t\t[ \"ui-icon-\" + currentOpts.collapsedIcon ] : [] ) )\n\t\t\t\t.join( \" \" ) );\n\n\t\t\t// Add new classes if an icon is supposed to be present\n\t\t\tif ( hasIcon ) {\n\t\t\t\tanchor.addClass(\n\t\t\t\t\t[ iconposClass( opts.iconpos !== undefined ?\n\t\t\t\t\t\topts.iconpos : currentOpts.iconpos ) ]\n\t\t\t\t\t\t.concat( isCollapsed ?\n\t\t\t\t\t\t\t[ \"ui-icon-\" + ( opts.collapsedIcon !== undefined ?\n\t\t\t\t\t\t\t\topts.collapsedIcon :\n\t\t\t\t\t\t\t\tcurrentOpts.collapsedIcon ) ] :\n\t\t\t\t\t\t\t[ \"ui-icon-\" + ( opts.expandedIcon !== undefined ?\n\t\t\t\t\t\t\t\topts.expandedIcon :\n\t\t\t\t\t\t\t\tcurrentOpts.expandedIcon ) ] )\n\t\t\t\t\t\t.join( \" \" ) );\n\t\t\t}\n\t\t}\n\n\t\tif ( opts.theme !== undefined ) {\n\t\t\toldTheme = this._themeClassFromOption( \"ui-btn-\", currentOpts.theme );\n\t\t\tnewTheme = this._themeClassFromOption( \"ui-btn-\", opts.theme );\n\t\t\tanchor.removeClass( oldTheme ).addClass( newTheme );\n\t\t}\n\n\t\tif ( opts.contentTheme !== undefined ) {\n\t\t\toldTheme = this._themeClassFromOption( \"ui-body-\",\n\t\t\t\tcurrentOpts.contentTheme );\n\t\t\tnewTheme = this._themeClassFromOption( \"ui-body-\",\n\t\t\t\topts.contentTheme );\n\t\t\tui.content.removeClass( oldTheme ).addClass( newTheme );\n\t\t}\n\n\t\tif ( opts.inset !== undefined ) {\n\t\t\telem.toggleClass( \"ui-collapsible-inset\", opts.inset );\n\t\t\thasCorners = !!( opts.inset && ( opts.corners || currentOpts.corners ) );\n\t\t}\n\n\t\tif ( opts.corners !== undefined ) {\n\t\t\thasCorners = !!( opts.corners && ( opts.inset || currentOpts.inset ) );\n\t\t}\n\n\t\tif ( hasCorners !== undefined ) {\n\t\t\telem.toggleClass( \"ui-corner-all\", hasCorners );\n\t\t}\n\n\t\tif ( opts.mini !== undefined ) {\n\t\t\tanchor.toggleClass( \"ui-mini\", opts.mini );\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tthis._applyOptions( options );\n\t\tthis._super( options );\n\t\tthis._renderedOptions = this._getOptions( this.options );\n\t},\n\n\t_handleExpandCollapse: function( isCollapse ) {\n\t\tvar opts = this._renderedOptions,\n\t\t\tui = this._ui;\n\n\t\tui.status.text( isCollapse ? opts.expandCueText : opts.collapseCueText );\n\t\tui.heading\n\t\t\t.toggleClass( \"ui-collapsible-heading-collapsed\", isCollapse )\n\t\t\t.find( \"a\" ).first()\n\t\t\t.toggleClass( \"ui-icon-\" + opts.expandedIcon, !isCollapse )\n\n\t\t\t// logic or cause same icon for expanded/collapsed state would remove the ui-icon-class\n\t\t\t.toggleClass( \"ui-icon-\" + opts.collapsedIcon, ( isCollapse || opts.expandedIcon === opts.collapsedIcon ) )\n\t\t\t.removeClass( $.mobile.activeBtnClass );\n\n\t\tthis.element.toggleClass( \"ui-collapsible-collapsed\", isCollapse );\n\t\tui.content\n\t\t\t.toggleClass( \"ui-collapsible-content-collapsed\", isCollapse )\n\t\t\t.attr( \"aria-hidden\", isCollapse )\n\t\t\t.trigger( \"updatelayout\" );\n\t\tthis.options.collapsed = isCollapse;\n\t\tthis._trigger( isCollapse ? \"collapse\" : \"expand\" );\n\t},\n\n\texpand: function() {\n\t\tthis._handleExpandCollapse( false );\n\t},\n\n\tcollapse: function() {\n\t\tthis._handleExpandCollapse( true );\n\t},\n\n\t_destroy: function() {\n\t\tvar ui = this._ui,\n\t\t\topts = this.options;\n\n\t\tif ( opts.enhanced ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( ui.placeholder ) {\n\t\t\tui.originalHeading.insertBefore( ui.placeholder );\n\t\t\tui.placeholder.remove();\n\t\t\tui.heading.remove();\n\t\t} else {\n\t\t\tui.status.remove();\n\t\t\tui.heading\n\t\t\t\t.removeClass( \"ui-collapsible-heading ui-collapsible-heading-collapsed\" )\n\t\t\t\t.children()\n\t\t\t\t\t.contents()\n\t\t\t\t\t\t.unwrap();\n\t\t}\n\n\t\tui.anchor.contents().unwrap();\n\t\tui.content.contents().unwrap();\n\t\tthis.element\n\t\t\t.removeClass( \"ui-collapsible ui-collapsible-collapsed \" +\n\t\t\t\t\"ui-collapsible-themed-content ui-collapsible-inset ui-corner-all\" );\n\t}\n});\n\n// Defaults to be used by all instances of collapsible if per-instance values\n// are unset or if nothing is specified by way of inheritance from an accordion.\n// Note that this hash does not contain options \"collapsed\" or \"heading\",\n// because those are not inheritable.\n$.mobile.collapsible.defaults = {\n\texpandCueText: \" click to expand contents\",\n\tcollapseCueText: \" click to collapse contents\",\n\tcollapsedIcon: \"plus\",\n\tcontentTheme: \"inherit\",\n\texpandedIcon: \"minus\",\n\ticonpos: \"left\",\n\tinset: true,\n\tcorners: true,\n\ttheme: \"inherit\",\n\tmini: false\n};\n\n})( jQuery );\n\n(function( $, undefined ) {\n\nvar uiScreenHiddenRegex = /\\bui-screen-hidden\\b/;\nfunction noHiddenClass( elements ) {\n\tvar index,\n\t\tlength = elements.length,\n\t\tresult = [];\n\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( !elements[ index ].className.match( uiScreenHiddenRegex ) ) {\n\t\t\tresult.push( elements[ index ] );\n\t\t}\n\t}\n\n\treturn $( result );\n}\n\n$.mobile.behaviors.addFirstLastClasses = {\n\t_getVisibles: function( $els, create ) {\n\t\tvar visibles;\n\n\t\tif ( create ) {\n\t\t\tvisibles = noHiddenClass( $els );\n\t\t} else {\n\t\t\tvisibles = $els.filter( \":visible\" );\n\t\t\tif ( visibles.length === 0 ) {\n\t\t\t\tvisibles = noHiddenClass( $els );\n\t\t\t}\n\t\t}\n\n\t\treturn visibles;\n\t},\n\n\t_addFirstLastClasses: function( $els, $visibles, create ) {\n\t\t$els.removeClass( \"ui-first-child ui-last-child\" );\n\t\t$visibles.eq( 0 ).addClass( \"ui-first-child\" ).end().last().addClass( \"ui-last-child\" );\n\t\tif ( !create ) {\n\t\t\tthis.element.trigger( \"updatelayout\" );\n\t\t}\n\t},\n\n\t_removeFirstLastClasses: function( $els ) {\n\t\t$els.removeClass( \"ui-first-child ui-last-child\" );\n\t}\n};\n\n})( jQuery );\n\n(function( $, undefined ) {\n\nvar childCollapsiblesSelector = \":mobile-collapsible, \" + $.mobile.collapsible.initSelector;\n\n$.widget( \"mobile.collapsibleset\", $.extend( {\n\n\t// The initSelector is deprecated as of 1.4.0. In 1.5.0 we will use\n\t// :jqmData(role='collapsibleset') which will allow us to get rid of the line\n\t// below altogether, because the autoinit will generate such an initSelector\n\tinitSelector: \":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')\",\n\n\toptions: $.extend( {\n\t\tenhanced: false\n\t}, $.mobile.collapsible.defaults ),\n\n\t_handleCollapsibleExpand: function( event ) {\n\t\tvar closestCollapsible = $( event.target ).closest( \".ui-collapsible\" );\n\n\t\tif ( closestCollapsible.parent().is( \":mobile-collapsibleset, :jqmData(role='collapsible-set')\" ) ) {\n\t\t\tclosestCollapsible\n\t\t\t\t.siblings( \".ui-collapsible:not(.ui-collapsible-collapsed)\" )\n\t\t\t\t.collapsible( \"collapse\" );\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tvar elem = this.element,\n\t\t\topts = this.options;\n\n\t\t$.extend( this, {\n\t\t\t_classes: \"\"\n\t\t});\n\n\t\tif ( !opts.enhanced ) {\n\t\t\telem.addClass( \"ui-collapsible-set \" +\n\t\t\t\tthis._themeClassFromOption( \"ui-group-theme-\", opts.theme ) + \" \" +\n\t\t\t\t( opts.corners && opts.inset ? \"ui-corner-all \" : \"\" ) );\n\t\t\tthis.element.find( $.mobile.collapsible.initSelector ).collapsible();\n\t\t}\n\n\t\tthis._on( elem, { collapsibleexpand: \"_handleCollapsibleExpand\" } );\n\t},\n\n\t_themeClassFromOption: function( prefix, value ) {\n\t\treturn ( value ? ( value === \"none\" ? \"\" : prefix + value ) : \"\" );\n\t},\n\n\t_init: function() {\n\t\tthis._refresh( true );\n\n\t\t// Because the corners are handled by the collapsible itself and the default state is collapsed\n\t\t// That was causing https://github.com/jquery/jquery-mobile/issues/4116\n\t\tthis.element\n\t\t\t.children( childCollapsiblesSelector )\n\t\t\t.filter( \":jqmData(collapsed='false')\" )\n\t\t\t.collapsible( \"expand\" );\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar ret, hasCorners,\n\t\t\telem = this.element,\n\t\t\tthemeClass = this._themeClassFromOption( \"ui-group-theme-\", options.theme );\n\n\t\tif ( themeClass ) {\n\t\t\telem\n\t\t\t\t.removeClass( this._themeClassFromOption( \"ui-group-theme-\", this.options.theme ) )\n\t\t\t\t.addClass( themeClass );\n\t\t}\n\n\t\tif ( options.inset !== undefined ) {\n\t\t\thasCorners = !!( options.inset && ( options.corners || this.options.corners ) );\n\t\t}\n\n\t\tif ( options.corners !== undefined ) {\n\t\t\thasCorners = !!( options.corners && ( options.inset || this.options.inset ) );\n\t\t}\n\n\t\tif ( hasCorners !== undefined ) {\n\t\t\telem.toggleClass( \"ui-corner-all\", hasCorners );\n\t\t}\n\n\t\tret = this._super( options );\n\t\tthis.element.children( \":mobile-collapsible\" ).collapsible( \"refresh\" );\n\t\treturn ret;\n\t},\n\n\t_destroy: function() {\n\t\tvar el = this.element;\n\n\t\tthis._removeFirstLastClasses( el.children( childCollapsiblesSelector ) );\n\t\tel\n\t\t\t.removeClass( \"ui-collapsible-set ui-corner-all \" +\n\t\t\t\tthis._themeClassFromOption( \"ui-group-theme-\", this.options.theme ) )\n\t\t\t.children( \":mobile-collapsible\" )\n\t\t\t.collapsible( \"destroy\" );\n\t},\n\n\t_refresh: function( create ) {\n\t\tvar collapsiblesInSet = this.element.children( childCollapsiblesSelector );\n\n\t\tthis.element.find( $.mobile.collapsible.initSelector ).not( \".ui-collapsible\" ).collapsible();\n\n\t\tthis._addFirstLastClasses( collapsiblesInSet, this._getVisibles( collapsiblesInSet, create ), create );\n\t},\n\n\trefresh: function() {\n\t\tthis._refresh( false );\n\t}\n}, $.mobile.behaviors.addFirstLastClasses ) );\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n// Deprecated in 1.4\n$.fn.fieldcontain = function(/* options */) {\n\treturn this.addClass( \"ui-field-contain\" );\n};\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.fn.grid = function( options ) {\n\treturn this.each(function() {\n\n\t\tvar $this = $( this ),\n\t\t\to = $.extend({\n\t\t\t\tgrid: null\n\t\t\t}, options ),\n\t\t\t$kids = $this.children(),\n\t\t\tgridCols = { solo:1, a:2, b:3, c:4, d:5 },\n\t\t\tgrid = o.grid,\n\t\t\titerator,\n\t\t\tletter;\n\n\t\t\tif ( !grid ) {\n\t\t\t\tif ( $kids.length <= 5 ) {\n\t\t\t\t\tfor ( letter in gridCols ) {\n\t\t\t\t\t\tif ( gridCols[ letter ] === $kids.length ) {\n\t\t\t\t\t\t\tgrid = letter;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tgrid = \"a\";\n\t\t\t\t\t$this.addClass( \"ui-grid-duo\" );\n\t\t\t\t}\n\t\t\t}\n\t\t\titerator = gridCols[grid];\n\n\t\t$this.addClass( \"ui-grid-\" + grid );\n\n\t\t$kids.filter( \":nth-child(\" + iterator + \"n+1)\" ).addClass( \"ui-block-a\" );\n\n\t\tif ( iterator > 1 ) {\n\t\t\t$kids.filter( \":nth-child(\" + iterator + \"n+2)\" ).addClass( \"ui-block-b\" );\n\t\t}\n\t\tif ( iterator > 2 ) {\n\t\t\t$kids.filter( \":nth-child(\" + iterator + \"n+3)\" ).addClass( \"ui-block-c\" );\n\t\t}\n\t\tif ( iterator > 3 ) {\n\t\t\t$kids.filter( \":nth-child(\" + iterator + \"n+4)\" ).addClass( \"ui-block-d\" );\n\t\t}\n\t\tif ( iterator > 4 ) {\n\t\t\t$kids.filter( \":nth-child(\" + iterator + \"n+5)\" ).addClass( \"ui-block-e\" );\n\t\t}\n\t});\n};\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.navbar\", {\n\toptions: {\n\t\ticonpos: \"top\",\n\t\tgrid: null\n\t},\n\n\t_create: function() {\n\n\t\tvar $navbar = this.element,\n\t\t\t$navbtns = $navbar.find( \"a, button\" ),\n\t\t\ticonpos = $navbtns.filter( \":jqmData(icon)\" ).length ? this.options.iconpos : undefined;\n\n\t\t$navbar.addClass( \"ui-navbar\" )\n\t\t\t.attr( \"role\", \"navigation\" )\n\t\t\t.find( \"ul\" )\n\t\t\t.jqmEnhanceable()\n\t\t\t.grid({ grid: this.options.grid });\n\n\t\t$navbtns\n\t\t\t.each( function() {\n\t\t\t\tvar icon = $.mobile.getAttribute( this, \"icon\" ),\n\t\t\t\t\ttheme = $.mobile.getAttribute( this, \"theme\" ),\n\t\t\t\t\tclasses = \"ui-btn\";\n\n\t\t\t\tif ( theme ) {\n\t\t\t\t\tclasses += \" ui-btn-\" + theme;\n\t\t\t\t}\n\t\t\t\tif ( icon ) {\n\t\t\t\t\tclasses += \" ui-icon-\" + icon + \" ui-btn-icon-\" + iconpos;\n\t\t\t\t}\n\t\t\t\t$( this ).addClass( classes );\n\t\t\t});\n\n\t\t$navbar.delegate( \"a\", \"vclick\", function( /* event */ ) {\n\t\t\tvar activeBtn = $( this );\n\n\t\t\tif ( !( activeBtn.hasClass( \"ui-state-disabled\" ) ||\n\n\t\t\t\t// DEPRECATED as of 1.4.0 - remove after 1.4.0 release\n\t\t\t\t// only ui-state-disabled should be present thereafter\n\t\t\t\tactiveBtn.hasClass( \"ui-disabled\" ) ||\n\t\t\t\tactiveBtn.hasClass( $.mobile.activeBtnClass ) ) ) {\n\n\t\t\t\t$navbtns.removeClass( $.mobile.activeBtnClass );\n\t\t\t\tactiveBtn.addClass( $.mobile.activeBtnClass );\n\n\t\t\t\t// The code below is a workaround to fix #1181\n\t\t\t\t$( document ).one( \"pagehide\", function() {\n\t\t\t\t\tactiveBtn.removeClass( $.mobile.activeBtnClass );\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// Buttons in the navbar with ui-state-persist class should regain their active state before page show\n\t\t$navbar.closest( \".ui-page\" ).bind( \"pagebeforeshow\", function() {\n\t\t\t$navbtns.filter( \".ui-state-persist\" ).addClass( $.mobile.activeBtnClass );\n\t\t});\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\nvar getAttr = $.mobile.getAttribute;\n\n$.widget( \"mobile.listview\", $.extend( {\n\n\toptions: {\n\t\ttheme: null,\n\t\tcountTheme: null, /* Deprecated in 1.4 */\n\t\tdividerTheme: null,\n\t\ticon: \"carat-r\",\n\t\tsplitIcon: \"carat-r\",\n\t\tsplitTheme: null,\n\t\tcorners: true,\n\t\tshadow: true,\n\t\tinset: false\n\t},\n\n\t_create: function() {\n\t\tvar t = this,\n\t\t\tlistviewClasses = \"\";\n\n\t\tlistviewClasses += t.options.inset ? \" ui-listview-inset\" : \"\";\n\n\t\tif ( !!t.options.inset ) {\n\t\t\tlistviewClasses += t.options.corners ? \" ui-corner-all\" : \"\";\n\t\t\tlistviewClasses += t.options.shadow ? \" ui-shadow\" : \"\";\n\t\t}\n\n\t\t// create listview markup\n\t\tt.element.addClass( \" ui-listview\" + listviewClasses );\n\n\t\tt.refresh( true );\n\t},\n\n\t// TODO: Remove in 1.5\n\t_findFirstElementByTagName: function( ele, nextProp, lcName, ucName ) {\n\t\tvar dict = {};\n\t\tdict[ lcName ] = dict[ ucName ] = true;\n\t\twhile ( ele ) {\n\t\t\tif ( dict[ ele.nodeName ] ) {\n\t\t\t\treturn ele;\n\t\t\t}\n\t\t\tele = ele[ nextProp ];\n\t\t}\n\t\treturn null;\n\t},\n\t// TODO: Remove in 1.5\n\t_addThumbClasses: function( containers ) {\n\t\tvar i, img, len = containers.length;\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\timg = $( this._findFirstElementByTagName( containers[ i ].firstChild, \"nextSibling\", \"img\", \"IMG\" ) );\n\t\t\tif ( img.length ) {\n\t\t\t\t$( this._findFirstElementByTagName( img[ 0 ].parentNode, \"parentNode\", \"li\", \"LI\" ) ).addClass( img.hasClass( \"ui-li-icon\" ) ? \"ui-li-has-icon\" : \"ui-li-has-thumb\" );\n\t\t\t}\n\t\t}\n\t},\n\n\t_getChildrenByTagName: function( ele, lcName, ucName ) {\n\t\tvar results = [],\n\t\t\tdict = {};\n\t\tdict[ lcName ] = dict[ ucName ] = true;\n\t\tele = ele.firstChild;\n\t\twhile ( ele ) {\n\t\t\tif ( dict[ ele.nodeName ] ) {\n\t\t\t\tresults.push( ele );\n\t\t\t}\n\t\t\tele = ele.nextSibling;\n\t\t}\n\t\treturn $( results );\n\t},\n\n\t_beforeListviewRefresh: $.noop,\n\t_afterListviewRefresh: $.noop,\n\n\trefresh: function( create ) {\n\t\tvar buttonClass, pos, numli, item, itemClass, itemTheme, itemIcon, icon, a,\n\t\t\tisDivider, startCount, newStartCount, value, last, splittheme, splitThemeClass, spliticon,\n\t\t\taltButtonClass, dividerTheme, li,\n\t\t\to = this.options,\n\t\t\t$list = this.element,\n\t\t\tol = !!$.nodeName( $list[ 0 ], \"ol\" ),\n\t\t\tstart = $list.attr( \"start\" ),\n\t\t\titemClassDict = {},\n\t\t\tcountBubbles = $list.find( \".ui-li-count\" ),\n\t\t\tcountTheme = getAttr( $list[ 0 ], \"counttheme\" ) || this.options.countTheme,\n\t\t\tcountThemeClass = countTheme ? \"ui-body-\" + countTheme : \"ui-body-inherit\";\n\n\t\tif ( o.theme ) {\n\t\t\t$list.addClass( \"ui-group-theme-\" + o.theme );\n\t\t}\n\n\t\t// Check if a start attribute has been set while taking a value of 0 into account\n\t\tif ( ol && ( start || start === 0 ) ) {\n\t\t\tstartCount = parseInt( start, 10 ) - 1;\n\t\t\t$list.css( \"counter-reset\", \"listnumbering \" + startCount );\n\t\t}\n\n\t\tthis._beforeListviewRefresh();\n\n\t\tli = this._getChildrenByTagName( $list[ 0 ], \"li\", \"LI\" );\n\n\t\tfor ( pos = 0, numli = li.length; pos < numli; pos++ ) {\n\t\t\titem = li.eq( pos );\n\t\t\titemClass = \"\";\n\n\t\t\tif ( create || item[ 0 ].className.search( /\\bui-li-static\\b|\\bui-li-divider\\b/ ) < 0 ) {\n\t\t\t\ta = this._getChildrenByTagName( item[ 0 ], \"a\", \"A\" );\n\t\t\t\tisDivider = ( getAttr( item[ 0 ], \"role\" ) === \"list-divider\" );\n\t\t\t\tvalue = item.attr( \"value\" );\n\t\t\t\titemTheme = getAttr( item[ 0 ], \"theme\" );\n\n\t\t\t\tif ( a.length && a[ 0 ].className.search( /\\bui-btn\\b/ ) < 0 && !isDivider ) {\n\t\t\t\t\titemIcon = getAttr( item[ 0 ], \"icon\" );\n\t\t\t\t\ticon = ( itemIcon === false ) ? false : ( itemIcon || o.icon );\n\n\t\t\t\t\t// TODO: Remove in 1.5 together with links.js (links.js / .ui-link deprecated in 1.4)\n\t\t\t\t\ta.removeClass( \"ui-link\" );\n\n\t\t\t\t\tbuttonClass = \"ui-btn\";\n\n\t\t\t\t\tif ( itemTheme ) {\n\t\t\t\t\t\tbuttonClass += \" ui-btn-\" + itemTheme;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( a.length > 1 ) {\n\t\t\t\t\t\titemClass = \"ui-li-has-alt\";\n\n\t\t\t\t\t\tlast = a.last();\n\t\t\t\t\t\tsplittheme = getAttr( last[ 0 ], \"theme\" ) || o.splitTheme || getAttr( item[ 0 ], \"theme\", true );\n\t\t\t\t\t\tsplitThemeClass = splittheme ? \" ui-btn-\" + splittheme : \"\";\n\t\t\t\t\t\tspliticon = getAttr( last[ 0 ], \"icon\" ) || getAttr( item[ 0 ], \"icon\" ) || o.splitIcon;\n\t\t\t\t\t\taltButtonClass = \"ui-btn ui-btn-icon-notext ui-icon-\" + spliticon + splitThemeClass;\n\n\t\t\t\t\t\tlast\n\t\t\t\t\t\t\t.attr( \"title\", $.trim( last.getEncodedText() ) )\n\t\t\t\t\t\t\t.addClass( altButtonClass )\n\t\t\t\t\t\t\t.empty();\n\n\t\t\t\t\t\t// Reduce to the first anchor, because only the first gets the buttonClass\n\t\t\t\t\t\ta = a.first();\n\t\t\t\t\t} else if ( icon ) {\n\t\t\t\t\t\tbuttonClass += \" ui-btn-icon-right ui-icon-\" + icon;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply buttonClass to the (first) anchor\n\t\t\t\t\ta.addClass( buttonClass );\n\t\t\t\t} else if ( isDivider ) {\n\t\t\t\t\tdividerTheme = ( getAttr( item[ 0 ], \"theme\" ) || o.dividerTheme || o.theme );\n\n\t\t\t\t\titemClass = \"ui-li-divider ui-bar-\" + ( dividerTheme ? dividerTheme : \"inherit\" );\n\n\t\t\t\t\titem.attr( \"role\", \"heading\" );\n\t\t\t\t} else if ( a.length <= 0 ) {\n\t\t\t\t\titemClass = \"ui-li-static ui-body-\" + ( itemTheme ? itemTheme : \"inherit\" );\n\t\t\t\t}\n\t\t\t\tif ( ol && value ) {\n\t\t\t\t\tnewStartCount = parseInt( value , 10 ) - 1;\n\n\t\t\t\t\titem.css( \"counter-reset\", \"listnumbering \" + newStartCount );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Instead of setting item class directly on the list item\n\t\t\t// at this point in time, push the item into a dictionary\n\t\t\t// that tells us what class to set on it so we can do this after this\n\t\t\t// processing loop is finished.\n\n\t\t\tif ( !itemClassDict[ itemClass ] ) {\n\t\t\t\titemClassDict[ itemClass ] = [];\n\t\t\t}\n\n\t\t\titemClassDict[ itemClass ].push( item[ 0 ] );\n\t\t}\n\n\t\t// Set the appropriate listview item classes on each list item.\n\t\t// The main reason we didn't do this\n\t\t// in the for-loop above is because we can eliminate per-item function overhead\n\t\t// by calling addClass() and children() once or twice afterwards. This\n\t\t// can give us a significant boost on platforms like WP7.5.\n\n\t\tfor ( itemClass in itemClassDict ) {\n\t\t\t$( itemClassDict[ itemClass ] ).addClass( itemClass );\n\t\t}\n\n\t\tcountBubbles.each( function() {\n\t\t\t$( this ).closest( \"li\" ).addClass( \"ui-li-has-count\" );\n\t\t});\n\t\tif ( countThemeClass ) {\n\t\t\tcountBubbles.not( \"[class*='ui-body-']\" ).addClass( countThemeClass );\n\t\t}\n\n\t\t// Deprecated in 1.4. From 1.5 you have to add class ui-li-has-thumb or ui-li-has-icon to the LI.\n\t\tthis._addThumbClasses( li );\n\t\tthis._addThumbClasses( li.find( \".ui-btn\" ) );\n\n\t\tthis._afterListviewRefresh();\n\n\t\tthis._addFirstLastClasses( li, this._getVisibles( li, create ), create );\n\t}\n}, $.mobile.behaviors.addFirstLastClasses ) );\n\n})( jQuery );\n\n(function( $, undefined ) {\n\nfunction defaultAutodividersSelector( elt ) {\n\t// look for the text in the given element\n\tvar text = $.trim( elt.text() ) || null;\n\n\tif ( !text ) {\n\t\treturn null;\n\t}\n\n\t// create the text for the divider (first uppercased letter)\n\ttext = text.slice( 0, 1 ).toUpperCase();\n\n\treturn text;\n}\n\n$.widget( \"mobile.listview\", $.mobile.listview, {\n\toptions: {\n\t\tautodividers: false,\n\t\tautodividersSelector: defaultAutodividersSelector\n\t},\n\n\t_beforeListviewRefresh: function() {\n\t\tif ( this.options.autodividers ) {\n\t\t\tthis._replaceDividers();\n\t\t\tthis._superApply( arguments );\n\t\t}\n\t},\n\n\t_replaceDividers: function() {\n\t\tvar i, lis, li, dividerText,\n\t\t\tlastDividerText = null,\n\t\t\tlist = this.element,\n\t\t\tdivider;\n\n\t\tlist.children( \"li:jqmData(role='list-divider')\" ).remove();\n\n\t\tlis = list.children( \"li\" );\n\n\t\tfor ( i = 0; i < lis.length ; i++ ) {\n\t\t\tli = lis[ i ];\n\t\t\tdividerText = this.options.autodividersSelector( $( li ) );\n\n\t\t\tif ( dividerText && lastDividerText !== dividerText ) {\n\t\t\t\tdivider = document.createElement( \"li\" );\n\t\t\t\tdivider.appendChild( document.createTextNode( dividerText ) );\n\t\t\t\tdivider.setAttribute( \"data-\" + $.mobile.ns + \"role\", \"list-divider\" );\n\t\t\t\tli.parentNode.insertBefore( divider, li );\n\t\t\t}\n\n\t\t\tlastDividerText = dividerText;\n\t\t}\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\nvar rdivider = /(^|\\s)ui-li-divider($|\\s)/,\n\trhidden = /(^|\\s)ui-screen-hidden($|\\s)/;\n\n$.widget( \"mobile.listview\", $.mobile.listview, {\n\toptions: {\n\t\thideDividers: false\n\t},\n\n\t_afterListviewRefresh: function() {\n\t\tvar items, idx, item, hideDivider = true;\n\n\t\tthis._superApply( arguments );\n\n\t\tif ( this.options.hideDividers ) {\n\t\t\titems = this._getChildrenByTagName( this.element[ 0 ], \"li\", \"LI\" );\n\t\t\tfor ( idx = items.length - 1 ; idx > -1 ; idx-- ) {\n\t\t\t\titem = items[ idx ];\n\t\t\t\tif ( item.className.match( rdivider ) ) {\n\t\t\t\t\tif ( hideDivider ) {\n\t\t\t\t\t\titem.className = item.className + \" ui-screen-hidden\";\n\t\t\t\t\t}\n\t\t\t\t\thideDivider = true;\n\t\t\t\t} else {\n\t\t\t\t\tif ( !item.className.match( rhidden ) ) {\n\t\t\t\t\t\thideDivider = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.mobile.nojs = function( target ) {\n\t$( \":jqmData(role='nojs')\", target ).addClass( \"ui-nojs\" );\n};\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.mobile.behaviors.formReset = {\n\t_handleFormReset: function() {\n\t\tthis._on( this.element.closest( \"form\" ), {\n\t\t\treset: function() {\n\t\t\t\tthis._delay( \"_reset\" );\n\t\t\t}\n\t\t});\n\t}\n};\n\n})( jQuery );\n\n/*\n* \"checkboxradio\" plugin\n*/\n\n(function( $, undefined ) {\n\nvar escapeId = $.mobile.path.hashToSelector;\n\n$.widget( \"mobile.checkboxradio\", $.extend( {\n\n\tinitSelector: \"input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))\",\n\n\toptions: {\n\t\ttheme: \"inherit\",\n\t\tmini: false,\n\t\twrapperClass: null,\n\t\tenhanced: false,\n\t\ticonpos: \"left\"\n\n\t},\n\t_create: function() {\n\t\tvar input = this.element,\n\t\t\to = this.options,\n\t\t\tinheritAttr = function( input, dataAttr ) {\n\t\t\t\treturn input.jqmData( dataAttr ) ||\n\t\t\t\t\tinput.closest( \"form, fieldset\" ).jqmData( dataAttr );\n\t\t\t},\n\t\t\tlabel = this.options.enhanced ?\n\t\t\t\t{\n\t\t\t\t\telement: this.element.siblings( \"label\" ),\n\t\t\t\t\tisParent: false\n\t\t\t\t} :\n\t\t\t\tthis._findLabel(),\n\t\t\tinputtype = input[0].type,\n\t\t\tcheckedClass = \"ui-\" + inputtype + \"-on\",\n\t\t\tuncheckedClass = \"ui-\" + inputtype + \"-off\";\n\n\t\tif ( inputtype !== \"checkbox\" && inputtype !== \"radio\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.element[0].disabled ) {\n\t\t\tthis.options.disabled = true;\n\t\t}\n\n\t\to.iconpos = inheritAttr( input, \"iconpos\" ) ||\n\t\t\tlabel.element.attr( \"data-\" + $.mobile.ns + \"iconpos\" ) || o.iconpos,\n\n\t\t// Establish options\n\t\to.mini = inheritAttr( input, \"mini\" ) || o.mini;\n\n\t\t// Expose for other methods\n\t\t$.extend( this, {\n\t\t\tinput: input,\n\t\t\tlabel: label.element,\n\t\t\tlabelIsParent: label.isParent,\n\t\t\tinputtype: inputtype,\n\t\t\tcheckedClass: checkedClass,\n\t\t\tuncheckedClass: uncheckedClass\n\t\t});\n\n\t\tif ( !this.options.enhanced ) {\n\t\t\tthis._enhance();\n\t\t}\n\n\t\tthis._on( label.element, {\n\t\t\tvmouseover: \"_handleLabelVMouseOver\",\n\t\t\tvclick: \"_handleLabelVClick\"\n\t\t});\n\n\t\tthis._on( input, {\n\t\t\tvmousedown: \"_cacheVals\",\n\t\t\tvclick: \"_handleInputVClick\",\n\t\t\tfocus: \"_handleInputFocus\",\n\t\t\tblur: \"_handleInputBlur\"\n\t\t});\n\n\t\tthis._handleFormReset();\n\t\tthis.refresh();\n\t},\n\n\t_findLabel: function() {\n\t\tvar parentLabel, label, isParent,\n\t\t\tinput = this.element,\n\t\t\tlabelsList = input[ 0 ].labels;\n\n\t\tif( labelsList && labelsList.length > 0 ) {\n\t\t\tlabel = $( labelsList[ 0 ] );\n\t\t\tisParent = $.contains( label[ 0 ], input[ 0 ] );\n\t\t} else {\n\t\t\tparentLabel = input.closest( \"label\" );\n\t\t\tisParent = ( parentLabel.length > 0 );\n\n\t\t\t// NOTE: Windows Phone could not find the label through a selector\n\t\t\t// filter works though.\n\t\t\tlabel = isParent ? parentLabel :\n\t\t\t\t$( this.document[ 0 ].getElementsByTagName( \"label\" ) )\n\t\t\t\t\t.filter( \"[for='\" + escapeId( input[ 0 ].id ) + \"']\" )\n\t\t\t\t\t.first();\n\t\t}\n\n\t\treturn {\n\t\t\telement: label,\n\t\t\tisParent: isParent\n\t\t};\n\t},\n\n\t_enhance: function() {\n\t\tthis.label.addClass( \"ui-btn ui-corner-all\");\n\n\t\tif ( this.labelIsParent ) {\n\t\t\tthis.input.add( this.label ).wrapAll( this._wrapper() );\n\t\t} else {\n\t\t\t//this.element.replaceWith( this.input.add( this.label ).wrapAll( this._wrapper() ) );\n\t\t\tthis.element.wrap( this._wrapper() );\n\t\t\tthis.element.parent().prepend( this.label );\n\t\t}\n\n\t\t// Wrap the input + label in a div\n\n\t\tthis._setOptions({\n\t\t\t\"theme\": this.options.theme,\n\t\t\t\"iconpos\": this.options.iconpos,\n\t\t\t\"mini\": this.options.mini\n\t\t});\n\n\t},\n\n\t_wrapper: function() {\n\t\treturn $( \"<div class='\"  +\n\t\t\t( this.options.wrapperClass ? this.options.wrapperClass : \"\" ) +\n\t\t\t\" ui-\" + this.inputtype +\n\t\t\t( this.options.disabled ? \" ui-state-disabled\" : \"\" ) + \"' ></div>\" );\n\t},\n\n\t_handleInputFocus: function() {\n\t\tthis.label.addClass( $.mobile.focusClass );\n\t},\n\n\t_handleInputBlur: function() {\n\t\tthis.label.removeClass( $.mobile.focusClass );\n\t},\n\n\t_handleInputVClick: function() {\n\t\t// Adds checked attribute to checked input when keyboard is used\n\t\tthis.element.prop( \"checked\", this.element.is( \":checked\" ) );\n\t\tthis._getInputSet().not( this.element ).prop( \"checked\", false );\n\t\tthis._updateAll( true );\n\t},\n\n\t_handleLabelVMouseOver: function( event ) {\n\t\tif ( this.label.parent().hasClass( \"ui-state-disabled\" ) ) {\n\t\t\tevent.stopPropagation();\n\t\t}\n\t},\n\n\t_handleLabelVClick: function( event ) {\n\t\tvar input = this.element;\n\n\t\tif ( input.is( \":disabled\" ) ) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tthis._cacheVals();\n\n\t\tinput.prop( \"checked\", this.inputtype === \"radio\" && true || !input.prop( \"checked\" ) );\n\n\t\t// trigger click handler's bound directly to the input as a substitute for\n\t\t// how label clicks behave normally in the browsers\n\t\t// TODO: it would be nice to let the browser's handle the clicks and pass them\n\t\t//       through to the associate input. we can swallow that click at the parent\n\t\t//       wrapper element level\n\t\tinput.triggerHandler( \"click\" );\n\n\t\t// Input set for common radio buttons will contain all the radio\n\t\t// buttons, but will not for checkboxes. clearing the checked status\n\t\t// of other radios ensures the active button state is applied properly\n\t\tthis._getInputSet().not( input ).prop( \"checked\", false );\n\n\t\tthis._updateAll();\n\t\treturn false;\n\t},\n\n\t_cacheVals: function() {\n\t\tthis._getInputSet().each( function() {\n\t\t\t$( this ).attr(\"data-\" + $.mobile.ns + \"cacheVal\", this.checked );\n\t\t});\n\t},\n\n\t// Returns those radio buttons that are supposed to be in the same group as\n\t// this radio button. In the case of a checkbox or a radio lacking a name\n\t// attribute, it returns this.element.\n\t_getInputSet: function() {\n\t\tvar selector, formId,\n\t\t\tradio = this.element[ 0 ],\n\t\t\tname = radio.name,\n\t\t\tform = radio.form,\n\t\t\tdoc = this.element.parents().last().get( 0 ),\n\n\t\t\t// A radio is always a member of its own group\n\t\t\tradios = this.element;\n\n\t\t// Only start running selectors if this is an attached radio button with a name\n\t\tif ( name && this.inputtype === \"radio\" && doc ) {\n\t\t\tselector = \"input[type='radio'][name='\" + escapeId( name ) + \"']\";\n\n\t\t\t// If we're inside a form\n\t\t\tif ( form ) {\n\t\t\t\tformId = form.getAttribute( \"id\" );\n\n\t\t\t\t// If the form has an ID, collect radios scattered throught the document which\n\t\t\t\t// nevertheless are part of the form by way of the value of their form attribute\n\t\t\t\tif ( formId ) {\n\t\t\t\t\tradios = $( selector + \"[form='\" + escapeId( formId ) + \"']\", doc );\n\t\t\t\t}\n\n\t\t\t\t// Also add to those the radios in the form itself\n\t\t\t\tradios = $( form ).find( selector ).filter( function() {\n\n\t\t\t\t\t// Some radios inside the form may belong to some other form by virtue of\n\t\t\t\t\t// having a form attribute defined on them, so we must filter them out here\n\t\t\t\t\treturn ( this.form === form );\n\t\t\t\t}).add( radios );\n\n\t\t\t// If we're outside a form\n\t\t\t} else {\n\n\t\t\t\t// Collect all those radios which are also outside of a form and match our name\n\t\t\t\tradios = $( selector, doc ).filter( function() {\n\t\t\t\t\treturn !this.form;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn radios;\n\t},\n\n\t_updateAll: function( changeTriggered ) {\n\t\tvar self = this;\n\n\t\tthis._getInputSet().each( function() {\n\t\t\tvar $this = $( this );\n\n\t\t\tif ( ( this.checked || self.inputtype === \"checkbox\" ) && !changeTriggered ) {\n\t\t\t\t$this.trigger( \"change\" );\n\t\t\t}\n\t\t})\n\t\t.checkboxradio( \"refresh\" );\n\t},\n\n\t_reset: function() {\n\t\tthis.refresh();\n\t},\n\n\t// Is the widget supposed to display an icon?\n\t_hasIcon: function() {\n\t\tvar controlgroup, controlgroupWidget,\n\t\t\tcontrolgroupConstructor = $.mobile.controlgroup;\n\n\t\t// If the controlgroup widget is defined ...\n\t\tif ( controlgroupConstructor ) {\n\t\t\tcontrolgroup = this.element.closest(\n\t\t\t\t\":mobile-controlgroup,\" +\n\t\t\t\tcontrolgroupConstructor.prototype.initSelector );\n\n\t\t\t// ... and the checkbox is in a controlgroup ...\n\t\t\tif ( controlgroup.length > 0 ) {\n\n\t\t\t\t// ... look for a controlgroup widget instance, and ...\n\t\t\t\tcontrolgroupWidget = $.data( controlgroup[ 0 ], \"mobile-controlgroup\" );\n\n\t\t\t\t// ... if found, decide based on the option value, ...\n\t\t\t\treturn ( ( controlgroupWidget ? controlgroupWidget.options.type :\n\n\t\t\t\t\t// ... otherwise decide based on the \"type\" data attribute.\n\t\t\t\t\tcontrolgroup.attr( \"data-\" + $.mobile.ns + \"type\" ) ) !== \"horizontal\" );\n\t\t\t}\n\t\t}\n\n\t\t// Normally, the widget displays an icon.\n\t\treturn true;\n\t},\n\n\trefresh: function() {\n\t\tvar isChecked = this.element[ 0 ].checked,\n\t\t\tactive = $.mobile.activeBtnClass,\n\t\t\ticonposClass = \"ui-btn-icon-\" + this.options.iconpos,\n\t\t\taddClasses = [],\n\t\t\tremoveClasses = [];\n\n\t\tif ( this._hasIcon() ) {\n\t\t\tremoveClasses.push( active );\n\t\t\taddClasses.push( iconposClass );\n\t\t} else {\n\t\t\tremoveClasses.push( iconposClass );\n\t\t\t( isChecked ? addClasses : removeClasses ).push( active );\n\t\t}\n\n\t\tif ( isChecked ) {\n\t\t\taddClasses.push( this.checkedClass );\n\t\t\tremoveClasses.push( this.uncheckedClass );\n\t\t} else {\n\t\t\taddClasses.push( this.uncheckedClass );\n\t\t\tremoveClasses.push( this.checkedClass );\n\t\t}\n\n\t\tthis.widget().toggleClass( \"ui-state-disabled\", this.element.prop( \"disabled\" ) );\n\n\t\tthis.label\n\t\t\t.addClass( addClasses.join( \" \" ) )\n\t\t\t.removeClass( removeClasses.join( \" \" ) );\n\t},\n\n\twidget: function() {\n\t\treturn this.label.parent();\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar label = this.label,\n\t\t\tcurrentOptions = this.options,\n\t\t\touter = this.widget(),\n\t\t\thasIcon = this._hasIcon();\n\n\t\tif ( options.disabled !== undefined ) {\n\t\t\tthis.input.prop( \"disabled\", !!options.disabled );\n\t\t\touter.toggleClass( \"ui-state-disabled\", !!options.disabled );\n\t\t}\n\t\tif ( options.mini !== undefined ) {\n\t\t\touter.toggleClass( \"ui-mini\", !!options.mini );\n\t\t}\n\t\tif ( options.theme !== undefined ) {\n\t\t\tlabel\n\t\t\t\t.removeClass( \"ui-btn-\" + currentOptions.theme )\n\t\t\t\t.addClass( \"ui-btn-\" + options.theme );\n\t\t}\n\t\tif ( options.wrapperClass !== undefined ) {\n\t\t\touter\n\t\t\t\t.removeClass( currentOptions.wrapperClass )\n\t\t\t\t.addClass( options.wrapperClass );\n\t\t}\n\t\tif ( options.iconpos !== undefined && hasIcon ) {\n\t\t\tlabel.removeClass( \"ui-btn-icon-\" + currentOptions.iconpos ).addClass( \"ui-btn-icon-\" + options.iconpos );\n\t\t} else if ( !hasIcon ) {\n\t\t\tlabel.removeClass( \"ui-btn-icon-\" + currentOptions.iconpos );\n\t\t}\n\t\tthis._super( options );\n\t}\n\n}, $.mobile.behaviors.formReset ) );\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.button\", {\n\n\tinitSelector: \"input[type='button'], input[type='submit'], input[type='reset']\",\n\n\toptions: {\n\t\ttheme: null,\n\t\ticon: null,\n\t\ticonpos: \"left\",\n\t\ticonshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */\n\t\tcorners: true,\n\t\tshadow: true,\n\t\tinline: null,\n\t\tmini: null,\n\t\twrapperClass: null,\n\t\tenhanced: false\n\t},\n\n\t_create: function() {\n\n\t\tif ( this.element.is( \":disabled\" ) ) {\n\t\t\tthis.options.disabled = true;\n\t\t}\n\n\t\tif ( !this.options.enhanced ) {\n\t\t\tthis._enhance();\n\t\t}\n\n\t\t$.extend( this, {\n\t\t\twrapper: this.element.parent()\n\t\t});\n\n\t\tthis._on( {\n\t\t\tfocus: function() {\n\t\t\t\tthis.widget().addClass( $.mobile.focusClass );\n\t\t\t},\n\n\t\t\tblur: function() {\n\t\t\t\tthis.widget().removeClass( $.mobile.focusClass );\n\t\t\t}\n\t\t});\n\n\t\tthis.refresh( true );\n\t},\n\n\t_enhance: function() {\n\t\tthis.element.wrap( this._button() );\n\t},\n\n\t_button: function() {\n\t\tvar options = this.options,\n\t\t\ticonClasses = this._getIconClasses( this.options );\n\n\t\treturn $(\"<div class='ui-btn ui-input-btn\" +\n\t\t\t( options.wrapperClass ? \" \" + options.wrapperClass : \"\" ) +\n\t\t\t( options.theme ? \" ui-btn-\" + options.theme : \"\" ) +\n\t\t\t( options.corners ? \" ui-corner-all\" : \"\" ) +\n\t\t\t( options.shadow ? \" ui-shadow\" : \"\" ) +\n\t\t\t( options.inline ? \" ui-btn-inline\" : \"\" ) +\n\t\t\t( options.mini ? \" ui-mini\" : \"\" ) +\n\t\t\t( options.disabled ? \" ui-state-disabled\" : \"\" ) +\n\t\t\t( iconClasses ? ( \" \" + iconClasses ) : \"\" ) +\n\t\t\t\"' >\" + this.element.val() + \"</div>\" );\n\t},\n\n\twidget: function() {\n\t\treturn this.wrapper;\n\t},\n\n\t_destroy: function() {\n\t\t\tthis.element.insertBefore( this.wrapper );\n\t\t\tthis.wrapper.remove();\n\t},\n\n\t_getIconClasses: function( options ) {\n\t\treturn ( options.icon ? ( \"ui-icon-\" + options.icon +\n\t\t\t( options.iconshadow ? \" ui-shadow-icon\" : \"\" ) + /* TODO: Deprecated in 1.4, remove in 1.5. */\n\t\t\t\" ui-btn-icon-\" + options.iconpos ) : \"\" );\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar outer = this.widget();\n\n\t\tif ( options.theme !== undefined ) {\n\t\t\touter\n\t\t\t\t.removeClass( this.options.theme )\n\t\t\t\t.addClass( \"ui-btn-\" + options.theme );\n\t\t}\n\t\tif ( options.corners !== undefined ) {\n\t\t\touter.toggleClass( \"ui-corner-all\", options.corners );\n\t\t}\n\t\tif ( options.shadow !== undefined ) {\n\t\t\touter.toggleClass( \"ui-shadow\", options.shadow );\n\t\t}\n\t\tif ( options.inline !== undefined ) {\n\t\t\touter.toggleClass( \"ui-btn-inline\", options.inline );\n\t\t}\n\t\tif ( options.mini !== undefined ) {\n\t\t\touter.toggleClass( \"ui-mini\", options.mini );\n\t\t}\n\t\tif ( options.disabled !== undefined ) {\n\t\t\tthis.element.prop( \"disabled\", options.disabled );\n\t\t\touter.toggleClass( \"ui-state-disabled\", options.disabled );\n\t\t}\n\n\t\tif ( options.icon !== undefined ||\n\t\t\t\toptions.iconshadow !== undefined || /* TODO: Deprecated in 1.4, remove in 1.5. */\n\t\t\t\toptions.iconpos !== undefined ) {\n\t\t\touter\n\t\t\t\t.removeClass( this._getIconClasses( this.options ) )\n\t\t\t\t.addClass( this._getIconClasses(\n\t\t\t\t\t$.extend( {}, this.options, options ) ) );\n\t\t}\n\n\t\tthis._super( options );\n\t},\n\n\trefresh: function( create ) {\n\t\tvar originalElement,\n\t\t\tisDisabled = this.element.prop( \"disabled\" );\n\n\t\tif ( this.options.icon && this.options.iconpos === \"notext\" && this.element.attr( \"title\" ) ) {\n\t\t\tthis.element.attr( \"title\", this.element.val() );\n\t\t}\n\t\tif ( !create ) {\n\t\t\toriginalElement = this.element.detach();\n\t\t\t$( this.wrapper ).text( this.element.val() ).append( originalElement );\n\t\t}\n\t\tif ( this.options.disabled !== isDisabled ) {\n\t\t\tthis._setOptions({ disabled: isDisabled });\n\t\t}\n\t}\n});\n\n})( jQuery );\n\n(function( $ ) {\n\tvar\tmeta = $( \"meta[name=viewport]\" ),\n\t\tinitialContent = meta.attr( \"content\" ),\n\t\tdisabledZoom = initialContent + \",maximum-scale=1, user-scalable=no\",\n\t\tenabledZoom = initialContent + \",maximum-scale=10, user-scalable=yes\",\n\t\tdisabledInitially = /(user-scalable[\\s]*=[\\s]*no)|(maximum-scale[\\s]*=[\\s]*1)[$,\\s]/.test( initialContent );\n\n\t$.mobile.zoom = $.extend( {}, {\n\t\tenabled: !disabledInitially,\n\t\tlocked: false,\n\t\tdisable: function( lock ) {\n\t\t\tif ( !disabledInitially && !$.mobile.zoom.locked ) {\n\t\t\t\tmeta.attr( \"content\", disabledZoom );\n\t\t\t\t$.mobile.zoom.enabled = false;\n\t\t\t\t$.mobile.zoom.locked = lock || false;\n\t\t\t}\n\t\t},\n\t\tenable: function( unlock ) {\n\t\t\tif ( !disabledInitially && ( !$.mobile.zoom.locked || unlock === true ) ) {\n\t\t\t\tmeta.attr( \"content\", enabledZoom );\n\t\t\t\t$.mobile.zoom.enabled = true;\n\t\t\t\t$.mobile.zoom.locked = false;\n\t\t\t}\n\t\t},\n\t\trestore: function() {\n\t\t\tif ( !disabledInitially ) {\n\t\t\t\tmeta.attr( \"content\", initialContent );\n\t\t\t\t$.mobile.zoom.enabled = true;\n\t\t\t}\n\t\t}\n\t});\n\n}( jQuery ));\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.textinput\", {\n\tinitSelector: \"input[type='text'],\" +\n\t\t\"input[type='search'],\" +\n\t\t\":jqmData(type='search'),\" +\n\t\t\"input[type='number'],\" +\n\t\t\":jqmData(type='number'),\" +\n\t\t\"input[type='password'],\" +\n\t\t\"input[type='email'],\" +\n\t\t\"input[type='url'],\" +\n\t\t\"input[type='tel'],\" +\n\t\t\"textarea,\" +\n\t\t\"input[type='time'],\" +\n\t\t\"input[type='date'],\" +\n\t\t\"input[type='month'],\" +\n\t\t\"input[type='week'],\" +\n\t\t\"input[type='datetime'],\" +\n\t\t\"input[type='datetime-local'],\" +\n\t\t\"input[type='color'],\" +\n\t\t\"input:not([type]),\" +\n\t\t\"input[type='file']\",\n\n\toptions: {\n\t\ttheme: null,\n\t\tcorners: true,\n\t\tmini: false,\n\t\t// This option defaults to true on iOS devices.\n\t\tpreventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( \"AppleWebKit\" ) > -1,\n\t\twrapperClass: \"\",\n\t\tenhanced: false\n\t},\n\n\t_create: function() {\n\n\t\tvar options = this.options,\n\t\t\tisSearch = this.element.is( \"[type='search'], :jqmData(type='search')\" ),\n\t\t\tisTextarea = this.element[ 0 ].tagName === \"TEXTAREA\",\n\t\t\tisRange = this.element.is( \"[data-\" + ( $.mobile.ns || \"\" ) + \"type='range']\" ),\n\t\t\tinputNeedsWrap = ( (this.element.is( \"input\" ) ||\n\t\t\t\tthis.element.is( \"[data-\" + ( $.mobile.ns || \"\" ) + \"type='search']\" ) ) &&\n\t\t\t\t\t!isRange );\n\n\t\tif ( this.element.prop( \"disabled\" ) ) {\n\t\t\toptions.disabled = true;\n\t\t}\n\n\t\t$.extend( this, {\n\t\t\tclasses: this._classesFromOptions(),\n\t\t\tisSearch: isSearch,\n\t\t\tisTextarea: isTextarea,\n\t\t\tisRange: isRange,\n\t\t\tinputNeedsWrap: inputNeedsWrap\n\t\t});\n\n\t\tthis._autoCorrect();\n\n\t\tif ( !options.enhanced ) {\n\t\t\tthis._enhance();\n\t\t}\n\n\t\tthis._on( {\n\t\t\t\"focus\": \"_handleFocus\",\n\t\t\t\"blur\": \"_handleBlur\"\n\t\t});\n\n\t},\n\n\trefresh: function() {\n\t\tthis.setOptions({\n\t\t\t\"disabled\" : this.element.is( \":disabled\" )\n\t\t});\n\t},\n\n\t_enhance: function() {\n\t\tvar elementClasses = [];\n\n\t\tif ( this.isTextarea ) {\n\t\t\telementClasses.push( \"ui-input-text\" );\n\t\t}\n\n\t\tif ( this.isTextarea || this.isRange ) {\n\t\t\telementClasses.push( \"ui-shadow-inset\" );\n\t\t}\n\n\t\t//\"search\" and \"text\" input widgets\n\t\tif ( this.inputNeedsWrap ) {\n\t\t\tthis.element.wrap( this._wrap() );\n\t\t} else {\n\t\t\telementClasses = elementClasses.concat( this.classes );\n\t\t}\n\n\t\tthis.element.addClass( elementClasses.join( \" \" ) );\n\t},\n\n\twidget: function() {\n\t\treturn ( this.inputNeedsWrap ) ? this.element.parent() : this.element;\n\t},\n\n\t_classesFromOptions: function() {\n\t\tvar options = this.options,\n\t\t\tclasses = [];\n\n\t\tclasses.push( \"ui-body-\" + ( ( options.theme === null ) ? \"inherit\" : options.theme ) );\n\t\tif ( options.corners ) {\n\t\t\tclasses.push( \"ui-corner-all\" );\n\t\t}\n\t\tif ( options.mini ) {\n\t\t\tclasses.push( \"ui-mini\" );\n\t\t}\n\t\tif ( options.disabled ) {\n\t\t\tclasses.push( \"ui-state-disabled\" );\n\t\t}\n\t\tif ( options.wrapperClass ) {\n\t\t\tclasses.push( options.wrapperClass );\n\t\t}\n\n\t\treturn classes;\n\t},\n\n\t_wrap: function() {\n\t\treturn $( \"<div class='\" +\n\t\t\t( this.isSearch ? \"ui-input-search \" : \"ui-input-text \" ) +\n\t\t\tthis.classes.join( \" \" ) + \" \" +\n\t\t\t\"ui-shadow-inset'></div>\" );\n\t},\n\n\t_autoCorrect: function() {\n\t\t// XXX: Temporary workaround for issue 785 (Apple bug 8910589).\n\t\t//      Turn off autocorrect and autocomplete on non-iOS 5 devices\n\t\t//      since the popup they use can't be dismissed by the user. Note\n\t\t//      that we test for the presence of the feature by looking for\n\t\t//      the autocorrect property on the input element. We currently\n\t\t//      have no test for iOS 5 or newer so we're temporarily using\n\t\t//      the touchOverflow support flag for jQM 1.0. Yes, I feel dirty.\n\t\t//      - jblas\n\t\tif ( typeof this.element[0].autocorrect !== \"undefined\" &&\n\t\t\t!$.support.touchOverflow ) {\n\n\t\t\t// Set the attribute instead of the property just in case there\n\t\t\t// is code that attempts to make modifications via HTML.\n\t\t\tthis.element[0].setAttribute( \"autocorrect\", \"off\" );\n\t\t\tthis.element[0].setAttribute( \"autocomplete\", \"off\" );\n\t\t}\n\t},\n\n\t_handleBlur: function() {\n\t\tthis.widget().removeClass( $.mobile.focusClass );\n\t\tif ( this.options.preventFocusZoom ) {\n\t\t\t$.mobile.zoom.enable( true );\n\t\t}\n\t},\n\n\t_handleFocus: function() {\n\t\t// In many situations, iOS will zoom into the input upon tap, this\n\t\t// prevents that from happening\n\t\tif ( this.options.preventFocusZoom ) {\n\t\t\t$.mobile.zoom.disable( true );\n\t\t}\n\t\tthis.widget().addClass( $.mobile.focusClass );\n\t},\n\n\t_setOptions: function ( options ) {\n\t\tvar outer = this.widget();\n\n\t\tthis._super( options );\n\n\t\tif ( !( options.disabled === undefined &&\n\t\t\toptions.mini === undefined &&\n\t\t\toptions.corners === undefined &&\n\t\t\toptions.theme === undefined &&\n\t\t\toptions.wrapperClass === undefined ) ) {\n\n\t\t\touter.removeClass( this.classes.join( \" \" ) );\n\t\t\tthis.classes = this._classesFromOptions();\n\t\t\touter.addClass( this.classes.join( \" \" ) );\n\t\t}\n\n\t\tif ( options.disabled !== undefined ) {\n\t\t\tthis.element.prop( \"disabled\", !!options.disabled );\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tif ( this.options.enhanced ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this.inputNeedsWrap ) {\n\t\t\tthis.element.unwrap();\n\t\t}\n\t\tthis.element.removeClass( \"ui-input-text \" + this.classes.join( \" \" ) );\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.slider\", $.extend( {\n\tinitSelector: \"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')\",\n\n\twidgetEventPrefix: \"slide\",\n\n\toptions: {\n\t\ttheme: null,\n\t\ttrackTheme: null,\n\t\tcorners: true,\n\t\tmini: false,\n\t\thighlight: false\n\t},\n\n\t_create: function() {\n\n\t\t// TODO: Each of these should have comments explain what they're for\n\t\tvar self = this,\n\t\t\tcontrol = this.element,\n\t\t\ttrackTheme = this.options.trackTheme || $.mobile.getAttribute( control[ 0 ], \"theme\" ),\n\t\t\ttrackThemeClass = trackTheme ? \" ui-bar-\" + trackTheme : \" ui-bar-inherit\",\n\t\t\tcornerClass = ( this.options.corners || control.jqmData( \"corners\" ) ) ? \" ui-corner-all\" : \"\",\n\t\t\tminiClass = ( this.options.mini || control.jqmData( \"mini\" ) ) ? \" ui-mini\" : \"\",\n\t\t\tcType = control[ 0 ].nodeName.toLowerCase(),\n\t\t\tisToggleSwitch = ( cType === \"select\" ),\n\t\t\tisRangeslider = control.parent().is( \":jqmData(role='rangeslider')\" ),\n\t\t\tselectClass = ( isToggleSwitch ) ? \"ui-slider-switch\" : \"\",\n\t\t\tcontrolID = control.attr( \"id\" ),\n\t\t\t$label = $( \"[for='\" + controlID + \"']\" ),\n\t\t\tlabelID = $label.attr( \"id\" ) || controlID + \"-label\",\n\t\t\tmin = !isToggleSwitch ? parseFloat( control.attr( \"min\" ) ) : 0,\n\t\t\tmax =  !isToggleSwitch ? parseFloat( control.attr( \"max\" ) ) : control.find( \"option\" ).length-1,\n\t\t\tstep = window.parseFloat( control.attr( \"step\" ) || 1 ),\n\t\t\tdomHandle = document.createElement( \"a\" ),\n\t\t\thandle = $( domHandle ),\n\t\t\tdomSlider = document.createElement( \"div\" ),\n\t\t\tslider = $( domSlider ),\n\t\t\tvaluebg = this.options.highlight && !isToggleSwitch ? (function() {\n\t\t\t\tvar bg = document.createElement( \"div\" );\n\t\t\t\tbg.className = \"ui-slider-bg \" + $.mobile.activeBtnClass;\n\t\t\t\treturn $( bg ).prependTo( slider );\n\t\t\t})() : false,\n\t\t\toptions,\n\t\t\twrapper,\n\t\t\tj, length,\n\t\t\ti, optionsCount, origTabIndex,\n\t\t\tside, activeClass, sliderImg;\n\n\t\t$label.attr( \"id\", labelID );\n\t\tthis.isToggleSwitch = isToggleSwitch;\n\n\t\tdomHandle.setAttribute( \"href\", \"#\" );\n\t\tdomSlider.setAttribute( \"role\", \"application\" );\n\t\tdomSlider.className = [ this.isToggleSwitch ? \"ui-slider ui-slider-track ui-shadow-inset \" : \"ui-slider-track ui-shadow-inset \", selectClass, trackThemeClass, cornerClass, miniClass ].join( \"\" );\n\t\tdomHandle.className = \"ui-slider-handle\";\n\t\tdomSlider.appendChild( domHandle );\n\n\t\thandle.attr({\n\t\t\t\"role\": \"slider\",\n\t\t\t\"aria-valuemin\": min,\n\t\t\t\"aria-valuemax\": max,\n\t\t\t\"aria-valuenow\": this._value(),\n\t\t\t\"aria-valuetext\": this._value(),\n\t\t\t\"title\": this._value(),\n\t\t\t\"aria-labelledby\": labelID\n\t\t});\n\n\t\t$.extend( this, {\n\t\t\tslider: slider,\n\t\t\thandle: handle,\n\t\t\tcontrol: control,\n\t\t\ttype: cType,\n\t\t\tstep: step,\n\t\t\tmax: max,\n\t\t\tmin: min,\n\t\t\tvaluebg: valuebg,\n\t\t\tisRangeslider: isRangeslider,\n\t\t\tdragging: false,\n\t\t\tbeforeStart: null,\n\t\t\tuserModified: false,\n\t\t\tmouseMoved: false\n\t\t});\n\n\t\tif ( isToggleSwitch ) {\n\t\t\t// TODO: restore original tabindex (if any) in a destroy method\n\t\t\torigTabIndex = control.attr( \"tabindex\" );\n\t\t\tif ( origTabIndex ) {\n\t\t\t\thandle.attr( \"tabindex\", origTabIndex );\n\t\t\t}\n\t\t\tcontrol.attr( \"tabindex\", \"-1\" ).focus(function() {\n\t\t\t\t$( this ).blur();\n\t\t\t\thandle.focus();\n\t\t\t});\n\n\t\t\twrapper = document.createElement( \"div\" );\n\t\t\twrapper.className = \"ui-slider-inneroffset\";\n\n\t\t\tfor ( j = 0, length = domSlider.childNodes.length; j < length; j++ ) {\n\t\t\t\twrapper.appendChild( domSlider.childNodes[j] );\n\t\t\t}\n\n\t\t\tdomSlider.appendChild( wrapper );\n\n\t\t\t// slider.wrapInner( \"<div class='ui-slider-inneroffset'></div>\" );\n\n\t\t\t// make the handle move with a smooth transition\n\t\t\thandle.addClass( \"ui-slider-handle-snapping\" );\n\n\t\t\toptions = control.find( \"option\" );\n\n\t\t\tfor ( i = 0, optionsCount = options.length; i < optionsCount; i++ ) {\n\t\t\t\tside = !i ? \"b\" : \"a\";\n\t\t\t\tactiveClass = !i ? \"\" : \" \" + $.mobile.activeBtnClass;\n\t\t\t\tsliderImg = document.createElement( \"span\" );\n\n\t\t\t\tsliderImg.className = [ \"ui-slider-label ui-slider-label-\", side, activeClass ].join( \"\" );\n\t\t\t\tsliderImg.setAttribute( \"role\", \"img\" );\n\t\t\t\tsliderImg.appendChild( document.createTextNode( options[i].innerHTML ) );\n\t\t\t\t$( sliderImg ).prependTo( slider );\n\t\t\t}\n\n\t\t\tself._labels = $( \".ui-slider-label\", slider );\n\n\t\t}\n\n\t\t// monitor the input for updated values\n\t\tcontrol.addClass( isToggleSwitch ? \"ui-slider-switch\" : \"ui-slider-input\" );\n\n\t\tthis._on( control, {\n\t\t\t\"change\": \"_controlChange\",\n\t\t\t\"keyup\": \"_controlKeyup\",\n\t\t\t\"blur\": \"_controlBlur\",\n\t\t\t\"vmouseup\": \"_controlVMouseUp\"\n\t\t});\n\n\t\tslider.bind( \"vmousedown\", $.proxy( this._sliderVMouseDown, this ) )\n\t\t\t.bind( \"vclick\", false );\n\n\t\t// We have to instantiate a new function object for the unbind to work properly\n\t\t// since the method itself is defined in the prototype (causing it to unbind everything)\n\t\tthis._on( document, { \"vmousemove\": \"_preventDocumentDrag\" });\n\t\tthis._on( slider.add( document ), { \"vmouseup\": \"_sliderVMouseUp\" });\n\n\t\tslider.insertAfter( control );\n\n\t\t// wrap in a div for styling purposes\n\t\tif ( !isToggleSwitch && !isRangeslider ) {\n\t\t\twrapper = this.options.mini ? \"<div class='ui-slider ui-mini'>\" : \"<div class='ui-slider'>\";\n\n\t\t\tcontrol.add( slider ).wrapAll( wrapper );\n\t\t}\n\n\t\t// bind the handle event callbacks and set the context to the widget instance\n\t\tthis._on( this.handle, {\n\t\t\t\"vmousedown\": \"_handleVMouseDown\",\n\t\t\t\"keydown\": \"_handleKeydown\",\n\t\t\t\"keyup\": \"_handleKeyup\"\n\t\t});\n\n\t\tthis.handle.bind( \"vclick\", false );\n\n\t\tthis._handleFormReset();\n\n\t\tthis.refresh( undefined, undefined, true );\n\t},\n\n\t_setOptions: function( options ) {\n\t\tif ( options.theme !== undefined ) {\n\t\t\tthis._setTheme( options.theme );\n\t\t}\n\n\t\tif ( options.trackTheme !== undefined ) {\n\t\t\tthis._setTrackTheme( options.trackTheme );\n\t\t}\n\n\t\tif ( options.corners !== undefined ) {\n\t\t\tthis._setCorners( options.corners );\n\t\t}\n\n\t\tif ( options.mini !== undefined ) {\n\t\t\tthis._setMini( options.mini );\n\t\t}\n\n\t\tif ( options.highlight !== undefined ) {\n\t\t\tthis._setHighlight( options.highlight );\n\t\t}\n\n\t\tif ( options.disabled !== undefined ) {\n\t\t\tthis._setDisabled( options.disabled );\n\t\t}\n\t\tthis._super( options );\n\t},\n\n\t_controlChange: function( event ) {\n\t\t// if the user dragged the handle, the \"change\" event was triggered from inside refresh(); don't call refresh() again\n\t\tif ( this._trigger( \"controlchange\", event ) === false ) {\n\t\t\treturn false;\n\t\t}\n\t\tif ( !this.mouseMoved ) {\n\t\t\tthis.refresh( this._value(), true );\n\t\t}\n\t},\n\n\t_controlKeyup: function(/* event */) { // necessary?\n\t\tthis.refresh( this._value(), true, true );\n\t},\n\n\t_controlBlur: function(/* event */) {\n\t\tthis.refresh( this._value(), true );\n\t},\n\n\t// it appears the clicking the up and down buttons in chrome on\n\t// range/number inputs doesn't trigger a change until the field is\n\t// blurred. Here we check thif the value has changed and refresh\n\t_controlVMouseUp: function(/* event */) {\n\t\tthis._checkedRefresh();\n\t},\n\n\t// NOTE force focus on handle\n\t_handleVMouseDown: function(/* event */) {\n\t\tthis.handle.focus();\n\t},\n\n\t_handleKeydown: function( event ) {\n\t\tvar index = this._value();\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// In all cases prevent the default and mark the handle as active\n\t\tswitch ( event.keyCode ) {\n\t\t\tcase $.mobile.keyCode.HOME:\n\t\t\tcase $.mobile.keyCode.END:\n\t\t\tcase $.mobile.keyCode.PAGE_UP:\n\t\t\tcase $.mobile.keyCode.PAGE_DOWN:\n\t\t\tcase $.mobile.keyCode.UP:\n\t\t\tcase $.mobile.keyCode.RIGHT:\n\t\t\tcase $.mobile.keyCode.DOWN:\n\t\t\tcase $.mobile.keyCode.LEFT:\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tif ( !this._keySliding ) {\n\t\t\t\t\tthis._keySliding = true;\n\t\t\t\t\tthis.handle.addClass( \"ui-state-active\" ); /* TODO: We don't use this class for styling. Do we need to add it? */\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// move the slider according to the keypress\n\t\tswitch ( event.keyCode ) {\n\t\t\tcase $.mobile.keyCode.HOME:\n\t\t\t\tthis.refresh( this.min );\n\t\t\t\tbreak;\n\t\t\tcase $.mobile.keyCode.END:\n\t\t\t\tthis.refresh( this.max );\n\t\t\t\tbreak;\n\t\t\tcase $.mobile.keyCode.PAGE_UP:\n\t\t\tcase $.mobile.keyCode.UP:\n\t\t\tcase $.mobile.keyCode.RIGHT:\n\t\t\t\tthis.refresh( index + this.step );\n\t\t\t\tbreak;\n\t\t\tcase $.mobile.keyCode.PAGE_DOWN:\n\t\t\tcase $.mobile.keyCode.DOWN:\n\t\t\tcase $.mobile.keyCode.LEFT:\n\t\t\t\tthis.refresh( index - this.step );\n\t\t\t\tbreak;\n\t\t}\n\t}, // remove active mark\n\n\t_handleKeyup: function(/* event */) {\n\t\tif ( this._keySliding ) {\n\t\t\tthis._keySliding = false;\n\t\t\tthis.handle.removeClass( \"ui-state-active\" ); /* See comment above. */\n\t\t}\n\t},\n\n\t_sliderVMouseDown: function( event ) {\n\t\t// NOTE: we don't do this in refresh because we still want to\n\t\t//       support programmatic alteration of disabled inputs\n\t\tif ( this.options.disabled || !( event.which === 1 || event.which === 0 || event.which === undefined ) ) {\n\t\t\treturn false;\n\t\t}\n\t\tif ( this._trigger( \"beforestart\", event ) === false ) {\n\t\t\treturn false;\n\t\t}\n\t\tthis.dragging = true;\n\t\tthis.userModified = false;\n\t\tthis.mouseMoved = false;\n\n\t\tif ( this.isToggleSwitch ) {\n\t\t\tthis.beforeStart = this.element[0].selectedIndex;\n\t\t}\n\n\t\tthis.refresh( event );\n\t\tthis._trigger( \"start\" );\n\t\treturn false;\n\t},\n\n\t_sliderVMouseUp: function() {\n\t\tif ( this.dragging ) {\n\t\t\tthis.dragging = false;\n\n\t\t\tif ( this.isToggleSwitch ) {\n\t\t\t\t// make the handle move with a smooth transition\n\t\t\t\tthis.handle.addClass( \"ui-slider-handle-snapping\" );\n\n\t\t\t\tif ( this.mouseMoved ) {\n\t\t\t\t\t// this is a drag, change the value only if user dragged enough\n\t\t\t\t\tif ( this.userModified ) {\n\t\t\t\t\t\tthis.refresh( this.beforeStart === 0 ? 1 : 0 );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.refresh( this.beforeStart );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// this is just a click, change the value\n\t\t\t\t\tthis.refresh( this.beforeStart === 0 ? 1 : 0 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.mouseMoved = false;\n\t\t\tthis._trigger( \"stop\" );\n\t\t\treturn false;\n\t\t}\n\t},\n\n\t_preventDocumentDrag: function( event ) {\n\t\t\t// NOTE: we don't do this in refresh because we still want to\n\t\t\t//       support programmatic alteration of disabled inputs\n\t\t\tif ( this._trigger( \"drag\", event ) === false) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif ( this.dragging && !this.options.disabled ) {\n\n\t\t\t\t// this.mouseMoved must be updated before refresh() because it will be used in the control \"change\" event\n\t\t\t\tthis.mouseMoved = true;\n\n\t\t\t\tif ( this.isToggleSwitch ) {\n\t\t\t\t\t// make the handle move in sync with the mouse\n\t\t\t\t\tthis.handle.removeClass( \"ui-slider-handle-snapping\" );\n\t\t\t\t}\n\n\t\t\t\tthis.refresh( event );\n\n\t\t\t\t// only after refresh() you can calculate this.userModified\n\t\t\t\tthis.userModified = this.beforeStart !== this.element[0].selectedIndex;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t_checkedRefresh: function() {\n\t\tif ( this.value !== this._value() ) {\n\t\t\tthis.refresh( this._value() );\n\t\t}\n\t},\n\n\t_value: function() {\n\t\treturn  this.isToggleSwitch ? this.element[0].selectedIndex : parseFloat( this.element.val() ) ;\n\t},\n\n\t_reset: function() {\n\t\tthis.refresh( undefined, false, true );\n\t},\n\n\trefresh: function( val, isfromControl, preventInputUpdate ) {\n\t\t// NOTE: we don't return here because we want to support programmatic\n\t\t//       alteration of the input value, which should still update the slider\n\n\t\tvar self = this,\n\t\t\tparentTheme = $.mobile.getAttribute( this.element[ 0 ], \"theme\" ),\n\t\t\ttheme = this.options.theme || parentTheme,\n\t\t\tthemeClass =  theme ? \" ui-btn-\" + theme : \"\",\n\t\t\ttrackTheme = this.options.trackTheme || parentTheme,\n\t\t\ttrackThemeClass = trackTheme ? \" ui-bar-\" + trackTheme : \" ui-bar-inherit\",\n\t\t\tcornerClass = this.options.corners ? \" ui-corner-all\" : \"\",\n\t\t\tminiClass = this.options.mini ? \" ui-mini\" : \"\",\n\t\t\tleft, width, data, tol,\n\t\t\tpxStep, percent,\n\t\t\tcontrol, isInput, optionElements, min, max, step,\n\t\t\tnewval, valModStep, alignValue, percentPerStep,\n\t\t\thandlePercent, aPercent, bPercent,\n\t\t\tvalueChanged;\n\n\t\tself.slider[0].className = [ this.isToggleSwitch ? \"ui-slider ui-slider-switch ui-slider-track ui-shadow-inset\" : \"ui-slider-track ui-shadow-inset\", trackThemeClass, cornerClass, miniClass ].join( \"\" );\n\t\tif ( this.options.disabled || this.element.prop( \"disabled\" ) ) {\n\t\t\tthis.disable();\n\t\t}\n\n\t\t// set the stored value for comparison later\n\t\tthis.value = this._value();\n\t\tif ( this.options.highlight && !this.isToggleSwitch && this.slider.find( \".ui-slider-bg\" ).length === 0 ) {\n\t\t\tthis.valuebg = (function() {\n\t\t\t\tvar bg = document.createElement( \"div\" );\n\t\t\t\tbg.className = \"ui-slider-bg \" + $.mobile.activeBtnClass;\n\t\t\t\treturn $( bg ).prependTo( self.slider );\n\t\t\t})();\n\t\t}\n\t\tthis.handle.addClass( \"ui-btn\" + themeClass + \" ui-shadow\" );\n\n\t\tcontrol = this.element;\n\t\tisInput = !this.isToggleSwitch;\n\t\toptionElements = isInput ? [] : control.find( \"option\" );\n\t\tmin =  isInput ? parseFloat( control.attr( \"min\" ) ) : 0;\n\t\tmax = isInput ? parseFloat( control.attr( \"max\" ) ) : optionElements.length - 1;\n\t\tstep = ( isInput && parseFloat( control.attr( \"step\" ) ) > 0 ) ? parseFloat( control.attr( \"step\" ) ) : 1;\n\n\t\tif ( typeof val === \"object\" ) {\n\t\t\tdata = val;\n\t\t\t// a slight tolerance helped get to the ends of the slider\n\t\t\ttol = 8;\n\n\t\t\tleft = this.slider.offset().left;\n\t\t\twidth = this.slider.width();\n\t\t\tpxStep = width/((max-min)/step);\n\t\t\tif ( !this.dragging ||\n\t\t\t\t\tdata.pageX < left - tol ||\n\t\t\t\t\tdata.pageX > left + width + tol ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( pxStep > 1 ) {\n\t\t\t\tpercent = ( ( data.pageX - left ) / width ) * 100;\n\t\t\t} else {\n\t\t\t\tpercent = Math.round( ( ( data.pageX - left ) / width ) * 100 );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( val == null ) {\n\t\t\t\tval = isInput ? parseFloat( control.val() || 0 ) : control[0].selectedIndex;\n\t\t\t}\n\t\t\tpercent = ( parseFloat( val ) - min ) / ( max - min ) * 100;\n\t\t}\n\n\t\tif ( isNaN( percent ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnewval = ( percent / 100 ) * ( max - min ) + min;\n\n\t\t//from jQuery UI slider, the following source will round to the nearest step\n\t\tvalModStep = ( newval - min ) % step;\n\t\talignValue = newval - valModStep;\n\n\t\tif ( Math.abs( valModStep ) * 2 >= step ) {\n\t\t\talignValue += ( valModStep > 0 ) ? step : ( -step );\n\t\t}\n\n\t\tpercentPerStep = 100/((max-min)/step);\n\t\t// Since JavaScript has problems with large floats, round\n\t\t// the final value to 5 digits after the decimal point (see jQueryUI: #4124)\n\t\tnewval = parseFloat( alignValue.toFixed(5) );\n\n\t\tif ( typeof pxStep === \"undefined\" ) {\n\t\t\tpxStep = width / ( (max-min) / step );\n\t\t}\n\t\tif ( pxStep > 1 && isInput ) {\n\t\t\tpercent = ( newval - min ) * percentPerStep * ( 1 / step );\n\t\t}\n\t\tif ( percent < 0 ) {\n\t\t\tpercent = 0;\n\t\t}\n\n\t\tif ( percent > 100 ) {\n\t\t\tpercent = 100;\n\t\t}\n\n\t\tif ( newval < min ) {\n\t\t\tnewval = min;\n\t\t}\n\n\t\tif ( newval > max ) {\n\t\t\tnewval = max;\n\t\t}\n\n\t\tthis.handle.css( \"left\", percent + \"%\" );\n\n\t\tthis.handle[0].setAttribute( \"aria-valuenow\", isInput ? newval : optionElements.eq( newval ).attr( \"value\" ) );\n\n\t\tthis.handle[0].setAttribute( \"aria-valuetext\", isInput ? newval : optionElements.eq( newval ).getEncodedText() );\n\n\t\tthis.handle[0].setAttribute( \"title\", isInput ? newval : optionElements.eq( newval ).getEncodedText() );\n\n\t\tif ( this.valuebg ) {\n\t\t\tthis.valuebg.css( \"width\", percent + \"%\" );\n\t\t}\n\n\t\t// drag the label widths\n\t\tif ( this._labels ) {\n\t\t\thandlePercent = this.handle.width() / this.slider.width() * 100;\n\t\t\taPercent = percent && handlePercent + ( 100 - handlePercent ) * percent / 100;\n\t\t\tbPercent = percent === 100 ? 0 : Math.min( handlePercent + 100 - aPercent, 100 );\n\n\t\t\tthis._labels.each(function() {\n\t\t\t\tvar ab = $( this ).hasClass( \"ui-slider-label-a\" );\n\t\t\t\t$( this ).width( ( ab ? aPercent : bPercent  ) + \"%\" );\n\t\t\t});\n\t\t}\n\n\t\tif ( !preventInputUpdate ) {\n\t\t\tvalueChanged = false;\n\n\t\t\t// update control\"s value\n\t\t\tif ( isInput ) {\n\t\t\t\tvalueChanged = parseFloat( control.val() ) !== newval;\n\t\t\t\tcontrol.val( newval );\n\t\t\t} else {\n\t\t\t\tvalueChanged = control[ 0 ].selectedIndex !== newval;\n\t\t\t\tcontrol[ 0 ].selectedIndex = newval;\n\t\t\t}\n\t\t\tif ( this._trigger( \"beforechange\", val ) === false) {\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif ( !isfromControl && valueChanged ) {\n\t\t\t\tcontrol.trigger( \"change\" );\n\t\t\t}\n\t\t}\n\t},\n\n\t_setHighlight: function( value ) {\n\t\tvalue = !!value;\n\t\tif ( value ) {\n\t\t\tthis.options.highlight = !!value;\n\t\t\tthis.refresh();\n\t\t} else if ( this.valuebg ) {\n\t\t\tthis.valuebg.remove();\n\t\t\tthis.valuebg = false;\n\t\t}\n\t},\n\n\t_setTheme: function( value ) {\n\t\tthis.handle\n\t\t\t.removeClass( \"ui-btn-\" + this.options.theme )\n\t\t\t.addClass( \"ui-btn-\" + value );\n\n\t\tvar currentTheme = this.options.theme ? this.options.theme : \"inherit\",\n\t\t\tnewTheme = value ? value : \"inherit\";\n\n\t\tthis.control\n\t\t\t.removeClass( \"ui-body-\" + currentTheme )\n\t\t\t.addClass( \"ui-body-\" + newTheme );\n\t},\n\n\t_setTrackTheme: function( value ) {\n\t\tvar currentTrackTheme = this.options.trackTheme ? this.options.trackTheme : \"inherit\",\n\t\t\tnewTrackTheme = value ? value : \"inherit\";\n\n\t\tthis.slider\n\t\t\t.removeClass( \"ui-body-\" + currentTrackTheme )\n\t\t\t.addClass( \"ui-body-\" + newTrackTheme );\n\t},\n\n\t_setMini: function( value ) {\n\t\tvalue = !!value;\n\t\tif ( !this.isToggleSwitch && !this.isRangeslider ) {\n\t\t\tthis.slider.parent().toggleClass( \"ui-mini\", value );\n\t\t\tthis.element.toggleClass( \"ui-mini\", value );\n\t\t}\n\t\tthis.slider.toggleClass( \"ui-mini\", value );\n\t},\n\n\t_setCorners: function( value ) {\n\t\tthis.slider.toggleClass( \"ui-corner-all\", value );\n\n\t\tif ( !this.isToggleSwitch ) {\n\t\t\tthis.control.toggleClass( \"ui-corner-all\", value );\n\t\t}\n\t},\n\n\t_setDisabled: function( value ) {\n\t\tvalue = !!value;\n\t\tthis.element.prop( \"disabled\", value );\n\t\tthis.slider\n\t\t\t.toggleClass( \"ui-state-disabled\", value )\n\t\t\t.attr( \"aria-disabled\", value );\n\n\t\tthis.element.toggleClass( \"ui-state-disabled\", value );\n\t}\n\n}, $.mobile.behaviors.formReset ) );\n\n})( jQuery );\n\n(function( $, undefined ) {\n\nvar popup;\n\nfunction getPopup() {\n\tif ( !popup ) {\n\t\tpopup = $( \"<div></div>\", {\n\t\t\t\"class\": \"ui-slider-popup ui-shadow ui-corner-all\"\n\t\t});\n\t}\n\treturn popup.clone();\n}\n\n$.widget( \"mobile.slider\", $.mobile.slider, {\n\toptions: {\n\t\tpopupEnabled: false,\n\t\tshowValue: false\n\t},\n\n\t_create: function() {\n\t\tthis._super();\n\n\t\t$.extend( this, {\n\t\t\t_currentValue: null,\n\t\t\t_popup: null,\n\t\t\t_popupVisible: false\n\t\t});\n\n\t\tthis._setOption( \"popupEnabled\", this.options.popupEnabled );\n\n\t\tthis._on( this.handle, { \"vmousedown\" : \"_showPopup\" } );\n\t\tthis._on( this.slider.add( this.document ), { \"vmouseup\" : \"_hidePopup\" } );\n\t\tthis._refresh();\n\t},\n\n\t// position the popup centered 5px above the handle\n\t_positionPopup: function() {\n\t\tvar dstOffset = this.handle.offset();\n\n\t\tthis._popup.offset( {\n\t\t\tleft: dstOffset.left + ( this.handle.width() - this._popup.width() ) / 2,\n\t\t\ttop: dstOffset.top - this._popup.outerHeight() - 5\n\t\t});\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"showValue\" ) {\n\t\t\tthis.handle.html( value && !this.options.mini ? this._value() : \"\" );\n\t\t} else if ( key === \"popupEnabled\" ) {\n\t\t\tif ( value && !this._popup ) {\n\t\t\t\tthis._popup = getPopup()\n\t\t\t\t\t.addClass( \"ui-body-\" + ( this.options.theme || \"a\" ) )\n\t\t\t\t\t.hide()\n\t\t\t\t\t.insertBefore( this.element );\n\t\t\t}\n\t\t}\n\t},\n\n\t// show value on the handle and in popup\n\trefresh: function() {\n\t\tthis._super.apply( this, arguments );\n\t\tthis._refresh();\n\t},\n\n\t_refresh: function() {\n\t\tvar o = this.options, newValue;\n\n\t\tif ( o.popupEnabled ) {\n\t\t\t// remove the title attribute from the handle (which is\n\t\t\t// responsible for the annoying tooltip); NB we have\n\t\t\t// to do it here as the jqm slider sets it every time\n\t\t\t// the slider's value changes :(\n\t\t\tthis.handle.removeAttr( \"title\" );\n\t\t}\n\n\t\tnewValue = this._value();\n\t\tif ( newValue === this._currentValue ) {\n\t\t\treturn;\n\t\t}\n\t\tthis._currentValue = newValue;\n\n\t\tif ( o.popupEnabled && this._popup ) {\n\t\t\tthis._positionPopup();\n\t\t\tthis._popup.html( newValue );\n\t\t}\n\n\t\tif ( o.showValue && !this.options.mini ) {\n\t\t\tthis.handle.html( newValue );\n\t\t}\n\t},\n\n\t_showPopup: function() {\n\t\tif ( this.options.popupEnabled && !this._popupVisible ) {\n\t\t\tthis.handle.html( \"\" );\n\t\t\tthis._popup.show();\n\t\t\tthis._positionPopup();\n\t\t\tthis._popupVisible = true;\n\t\t}\n\t},\n\n\t_hidePopup: function() {\n\t\tvar o = this.options;\n\n\t\tif ( o.popupEnabled && this._popupVisible ) {\n\t\t\tif ( o.showValue && !o.mini ) {\n\t\t\t\tthis.handle.html( this._value() );\n\t\t\t}\n\t\t\tthis._popup.hide();\n\t\t\tthis._popupVisible = false;\n\t\t}\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.flipswitch\", $.extend({\n\n\toptions: {\n\t\tonText: \"On\",\n\t\toffText: \"Off\",\n\t\ttheme: null,\n\t\tenhanced: false,\n\t\twrapperClass: null,\n\t\tcorners: true,\n\t\tmini: false\n\t},\n\n\t_create: function() {\n\t\t\tif ( !this.options.enhanced ) {\n\t\t\t\tthis._enhance();\n\t\t\t} else {\n\t\t\t\t$.extend( this, {\n\t\t\t\t\tflipswitch: this.element.parent(),\n\t\t\t\t\ton: this.element.find( \".ui-flipswitch-on\" ).eq( 0 ),\n\t\t\t\t\toff: this.element.find( \".ui-flipswitch-off\" ).eq(0),\n\t\t\t\t\ttype: this.element.get( 0 ).tagName\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis._handleFormReset();\n\n\t\t\t// Transfer tabindex to \"on\" element and make input unfocusable\n\t\t\tthis._originalTabIndex = this.element.attr( \"tabindex\" );\n\t\t\tif ( this._originalTabIndex != null ) {\n\t\t\t\tthis.on.attr( \"tabindex\", this._originalTabIndex );\n\t\t\t}\n\t\t\tthis.element.attr( \"tabindex\", \"-1\" );\n\t\t\tthis._on({\n\t\t\t\t\"focus\" : \"_handleInputFocus\"\n\t\t\t});\n\n\t\t\tif ( this.element.is( \":disabled\" ) ) {\n\t\t\t\tthis._setOptions({\n\t\t\t\t\t\"disabled\": true\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis._on( this.flipswitch, {\n\t\t\t\t\"click\": \"_toggle\",\n\t\t\t\t\"swipeleft\": \"_left\",\n\t\t\t\t\"swiperight\": \"_right\"\n\t\t\t});\n\n\t\t\tthis._on( this.on, {\n\t\t\t\t\"keydown\": \"_keydown\"\n\t\t\t});\n\n\t\t\tthis._on( {\n\t\t\t\t\"change\": \"refresh\"\n\t\t\t});\n\t},\n\n\t_handleInputFocus: function() {\n\t\tthis.on.focus();\n\t},\n\n\twidget: function() {\n\t\treturn this.flipswitch;\n\t},\n\n\t_left: function() {\n\t\tthis.flipswitch.removeClass( \"ui-flipswitch-active\" );\n\t\tif ( this.type === \"SELECT\" ) {\n\t\t\tthis.element.get( 0 ).selectedIndex = 0;\n\t\t} else {\n\t\t\tthis.element.prop( \"checked\", false );\n\t\t}\n\t\tthis.element.trigger( \"change\" );\n\t},\n\n\t_right: function() {\n\t\tthis.flipswitch.addClass( \"ui-flipswitch-active\" );\n\t\tif ( this.type === \"SELECT\" ) {\n\t\t\tthis.element.get( 0 ).selectedIndex = 1;\n\t\t} else {\n\t\t\tthis.element.prop( \"checked\", true );\n\t\t}\n\t\tthis.element.trigger( \"change\" );\n\t},\n\n\t_enhance: function() {\n\t\tvar flipswitch = $( \"<div>\" ),\n\t\t\toptions = this.options,\n\t\t\telement = this.element,\n\t\t\ttheme = options.theme ? options.theme : \"inherit\",\n\n\t\t\t// The \"on\" button is an anchor so it's focusable\n\t\t\ton = $( \"<a></a>\", {\n\t\t\t\t\"href\": \"#\"\n\t\t\t}),\n\t\t\toff = $( \"<span></span>\" ),\n\t\t\ttype = element.get( 0 ).tagName,\n\t\t\tonText = ( type === \"INPUT\" ) ?\n\t\t\t\toptions.onText : element.find( \"option\" ).eq( 1 ).text(),\n\t\t\toffText = ( type === \"INPUT\" ) ?\n\t\t\t\toptions.offText : element.find( \"option\" ).eq( 0 ).text();\n\n\t\t\ton\n\t\t\t\t.addClass( \"ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit\" )\n\t\t\t\t.text( onText );\n\t\t\toff\n\t\t\t\t.addClass( \"ui-flipswitch-off\" )\n\t\t\t\t.text( offText );\n\n\t\t\tflipswitch\n\t\t\t\t.addClass( \"ui-flipswitch ui-shadow-inset \" +\n\t\t\t\t\t\"ui-bar-\" + theme + \" \" +\n\t\t\t\t\t( options.wrapperClass ? options.wrapperClass : \"\" ) + \" \" +\n\t\t\t\t\t( ( element.is( \":checked\" ) ||\n\t\t\t\t\t\telement\n\t\t\t\t\t\t\t.find( \"option\" )\n\t\t\t\t\t\t\t.eq( 1 )\n\t\t\t\t\t\t\t.is( \":selected\" ) ) ? \"ui-flipswitch-active\" : \"\" ) +\n\t\t\t\t\t( element.is(\":disabled\") ? \" ui-state-disabled\": \"\") +\n\t\t\t\t\t( options.corners ? \" ui-corner-all\": \"\" ) +\n\t\t\t\t\t( options.mini ? \" ui-mini\": \"\" ) )\n\t\t\t\t.append( on, off );\n\n\t\t\telement\n\t\t\t\t.addClass( \"ui-flipswitch-input\" )\n\t\t\t\t.after( flipswitch )\n\t\t\t\t.appendTo( flipswitch );\n\n\t\t$.extend( this, {\n\t\t\tflipswitch: flipswitch,\n\t\t\ton: on,\n\t\t\toff: off,\n\t\t\ttype: type\n\t\t});\n\t},\n\n\t_reset: function() {\n\t\tthis.refresh();\n\t},\n\n\trefresh: function() {\n\t\tvar direction,\n\t\t\texistingDirection = this.flipswitch.hasClass( \"ui-flipswitch-active\" ) ? \"_right\" : \"_left\";\n\n\t\tif ( this.type === \"SELECT\" ) {\n\t\t\tdirection = ( this.element.get( 0 ).selectedIndex > 0 ) ? \"_right\": \"_left\";\n\t\t} else {\n\t\t\tdirection = this.element.prop( \"checked\" ) ? \"_right\": \"_left\";\n\t\t}\n\n\t\tif ( direction !== existingDirection ) {\n\t\t\tthis[ direction ]();\n\t\t}\n\t},\n\n\t_toggle: function() {\n\t\tvar direction = this.flipswitch.hasClass( \"ui-flipswitch-active\" ) ? \"_left\" : \"_right\";\n\n\t\tthis[ direction ]();\n\t},\n\n\t_keydown: function( e ) {\n\t\tif ( e.which === $.mobile.keyCode.LEFT ) {\n\t\t\tthis._left();\n\t\t} else if ( e.which === $.mobile.keyCode.RIGHT ) {\n\t\t\tthis._right();\n\t\t} else if ( e.which === $.mobile.keyCode.SPACE ) {\n\t\t\tthis._toggle();\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tif ( options.theme !== undefined ) {\n\t\t\tvar currentTheme = options.theme ? options.theme : \"inherit\",\n\t\t\t\tnewTheme = options.theme ? options.theme : \"inherit\";\n\n\t\t\tthis.widget()\n\t\t\t\t.removeClass( \"ui-bar-\" + currentTheme )\n\t\t\t\t.addClass( \"ui-bar-\" + newTheme );\n\t\t}\n\t\tif ( options.onText !== undefined ) {\n\t\t\tthis.on.text( options.onText );\n\t\t}\n\t\tif ( options.offText !== undefined ) {\n\t\t\tthis.off.text( options.offText );\n\t\t}\n\t\tif ( options.disabled !== undefined ) {\n\t\t\tthis.widget().toggleClass( \"ui-state-disabled\", options.disabled );\n\t\t}\n\t\tif ( options.mini !== undefined ) {\n\t\t\tthis.widget().toggleClass( \"ui-mini\", options.mini );\n\t\t}\n\t\tif ( options.corners !== undefined ) {\n\t\t\tthis.widget().toggleClass( \"ui-corner-all\", options.corners );\n\t\t}\n\n\t\tthis._super( options );\n\t},\n\n\t_destroy: function() {\n\t\tif ( this.options.enhanced ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._originalTabIndex != null ) {\n\t\t\tthis.element.attr( \"tabindex\", this._originalTabIndex );\n\t\t} else {\n\t\t\tthis.element.removeAttr( \"tabindex\" );\n\t\t}\n\t\tthis.on.remove();\n\t\tthis.off.remove();\n\t\tthis.element.unwrap();\n\t\tthis.flipswitch.remove();\n\t\tthis.removeClass( \"ui-flipswitch-input\" );\n\t}\n\n}, $.mobile.behaviors.formReset ) );\n\n})( jQuery );\n\n(function( $, undefined ) {\n\t$.widget( \"mobile.rangeslider\", $.extend( {\n\n\t\toptions: {\n\t\t\ttheme: null,\n\t\t\ttrackTheme: null,\n\t\t\tcorners: true,\n\t\t\tmini: false,\n\t\t\thighlight: true\n\t\t},\n\n\t\t_create: function() {\n\t\t\tvar $el = this.element,\n\t\t\telClass = this.options.mini ? \"ui-rangeslider ui-mini\" : \"ui-rangeslider\",\n\t\t\t_inputFirst = $el.find( \"input\" ).first(),\n\t\t\t_inputLast = $el.find( \"input\" ).last(),\n\t\t\t_label = $el.find( \"label\" ).first(),\n\t\t\t_sliderWidgetFirst = $.data( _inputFirst.get( 0 ), \"mobile-slider\" ) ||\n\t\t\t\t$.data( _inputFirst.slider().get( 0 ), \"mobile-slider\" ),\n\t\t\t_sliderWidgetLast = $.data( _inputLast.get(0), \"mobile-slider\" ) ||\n\t\t\t\t$.data( _inputLast.slider().get( 0 ), \"mobile-slider\" ),\n\t\t\t_sliderFirst = _sliderWidgetFirst.slider,\n\t\t\t_sliderLast = _sliderWidgetLast.slider,\n\t\t\tfirstHandle = _sliderWidgetFirst.handle,\n\t\t\t_sliders = $( \"<div class='ui-rangeslider-sliders' />\" ).appendTo( $el );\n\n\t\t\t_inputFirst.addClass( \"ui-rangeslider-first\" );\n\t\t\t_inputLast.addClass( \"ui-rangeslider-last\" );\n\t\t\t$el.addClass( elClass );\n\n\t\t\t_sliderFirst.appendTo( _sliders );\n\t\t\t_sliderLast.appendTo( _sliders );\n\t\t\t_label.insertBefore( $el );\n\t\t\tfirstHandle.prependTo( _sliderLast );\n\n\t\t\t$.extend( this, {\n\t\t\t\t_inputFirst: _inputFirst,\n\t\t\t\t_inputLast: _inputLast,\n\t\t\t\t_sliderFirst: _sliderFirst,\n\t\t\t\t_sliderLast: _sliderLast,\n\t\t\t\t_label: _label,\n\t\t\t\t_targetVal: null,\n\t\t\t\t_sliderTarget: false,\n\t\t\t\t_sliders: _sliders,\n\t\t\t\t_proxy: false\n\t\t\t});\n\n\t\t\tthis.refresh();\n\t\t\tthis._on( this.element.find( \"input.ui-slider-input\" ), {\n\t\t\t\t\"slidebeforestart\": \"_slidebeforestart\",\n\t\t\t\t\"slidestop\": \"_slidestop\",\n\t\t\t\t\"slidedrag\": \"_slidedrag\",\n\t\t\t\t\"slidebeforechange\": \"_change\",\n\t\t\t\t\"blur\": \"_change\",\n\t\t\t\t\"keyup\": \"_change\"\n\t\t\t});\n\t\t\tthis._on({\n\t\t\t\t\"mousedown\":\"_change\"\n\t\t\t});\n\t\t\tthis._on( this.element.closest( \"form\" ), {\n\t\t\t\t\"reset\":\"_handleReset\"\n\t\t\t});\n\t\t\tthis._on( firstHandle, {\n\t\t\t\t\"vmousedown\": \"_dragFirstHandle\"\n\t\t\t});\n\t\t},\n\t\t_handleReset: function() {\n\t\t\tvar self = this;\n\t\t\t//we must wait for the stack to unwind before updateing other wise sliders will not have updated yet\n\t\t\tsetTimeout( function() {\n\t\t\t\tself._updateHighlight();\n\t\t\t},0);\n\t\t},\n\n\t\t_dragFirstHandle: function( event ) {\n\t\t\t//if the first handle is dragged send the event to the first slider\n\t\t\t$.data( this._inputFirst.get(0), \"mobile-slider\" ).dragging = true;\n\t\t\t$.data( this._inputFirst.get(0), \"mobile-slider\" ).refresh( event );\n\t\t\t$.data( this._inputFirst.get(0), \"mobile-slider\" )._trigger( \"start\" );\n\t\t\treturn false;\n\t\t},\n\n\t\t_slidedrag: function( event ) {\n\t\t\tvar first = $( event.target ).is( this._inputFirst ),\n\t\t\t\totherSlider = ( first ) ? this._inputLast : this._inputFirst;\n\n\t\t\tthis._sliderTarget = false;\n\t\t\t//if the drag was initiated on an extreme and the other handle is focused send the events to\n\t\t\t//the closest handle\n\t\t\tif ( ( this._proxy === \"first\" && first ) || ( this._proxy === \"last\" && !first ) ) {\n\t\t\t\t$.data( otherSlider.get(0), \"mobile-slider\" ).dragging = true;\n\t\t\t\t$.data( otherSlider.get(0), \"mobile-slider\" ).refresh( event );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\t_slidestop: function( event ) {\n\t\t\tvar first = $( event.target ).is( this._inputFirst );\n\n\t\t\tthis._proxy = false;\n\t\t\t//this stops dragging of the handle and brings the active track to the front\n\t\t\t//this makes clicks on the track go the the last handle used\n\t\t\tthis.element.find( \"input\" ).trigger( \"vmouseup\" );\n\t\t\tthis._sliderFirst.css( \"z-index\", first ? 1 : \"\" );\n\t\t},\n\n\t\t_slidebeforestart: function( event ) {\n\t\t\tthis._sliderTarget = false;\n\t\t\t//if the track is the target remember this and the original value\n\t\t\tif ( $( event.originalEvent.target ).hasClass( \"ui-slider-track\" ) ) {\n\t\t\t\tthis._sliderTarget = true;\n\t\t\t\tthis._targetVal = $( event.target ).val();\n\t\t\t}\n\t\t},\n\n\t\t_setOptions: function( options ) {\n\t\t\tif ( options.theme !== undefined ) {\n\t\t\t\tthis._setTheme( options.theme );\n\t\t\t}\n\n\t\t\tif ( options.trackTheme !== undefined ) {\n\t\t\t\tthis._setTrackTheme( options.trackTheme );\n\t\t\t}\n\n\t\t\tif ( options.mini !== undefined ) {\n\t\t\t\tthis._setMini( options.mini );\n\t\t\t}\n\n\t\t\tif ( options.highlight !== undefined ) {\n\t\t\t\tthis._setHighlight( options.highlight );\n\t\t\t}\n\n\t\t\tif ( options.disabled !== undefined ) {\n\t\t\t\tthis._setDisabled( options.disabled );\n\t\t\t}\n\n\t\t\tthis._super( options );\n\t\t\tthis.refresh();\n\t\t},\n\n\t\trefresh: function() {\n\t\t\tvar $el = this.element,\n\t\t\t\to = this.options;\n\n\t\t\tif ( this._inputFirst.is( \":disabled\" ) || this._inputLast.is( \":disabled\" ) ) {\n\t\t\t\tthis.options.disabled = true;\n\t\t\t}\n\n\t\t\t$el.find( \"input\" ).slider({\n\t\t\t\ttheme: o.theme,\n\t\t\t\ttrackTheme: o.trackTheme,\n\t\t\t\tdisabled: o.disabled,\n\t\t\t\tcorners: o.corners,\n\t\t\t\tmini: o.mini,\n\t\t\t\thighlight: o.highlight\n\t\t\t}).slider( \"refresh\" );\n\t\t\tthis._updateHighlight();\n\t\t},\n\n\t\t_change: function( event ) {\n\t\t\tif ( event.type === \"keyup\" ) {\n\t\t\t\tthis._updateHighlight();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar self = this,\n\t\t\t\tmin = parseFloat( this._inputFirst.val(), 10 ),\n\t\t\t\tmax = parseFloat( this._inputLast.val(), 10 ),\n\t\t\t\tfirst = $( event.target ).hasClass( \"ui-rangeslider-first\" ),\n\t\t\t\tthisSlider = first ? this._inputFirst : this._inputLast,\n\t\t\t\totherSlider = first ? this._inputLast : this._inputFirst;\n\n\t\t\tif ( ( this._inputFirst.val() > this._inputLast.val() && event.type === \"mousedown\" && !$(event.target).hasClass(\"ui-slider-handle\")) ) {\n\t\t\t\tthisSlider.blur();\n\t\t\t} else if ( event.type === \"mousedown\" ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( min > max && !this._sliderTarget ) {\n\t\t\t\t//this prevents min from being greater then max\n\t\t\t\tthisSlider.val( first ? max: min ).slider( \"refresh\" );\n\t\t\t\tthis._trigger( \"normalize\" );\n\t\t\t} else if ( min > max ) {\n\t\t\t\t//this makes it so clicks on the target on either extreme go to the closest handle\n\t\t\t\tthisSlider.val( this._targetVal ).slider( \"refresh\" );\n\n\t\t\t\t//You must wait for the stack to unwind so first slider is updated before updating second\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\totherSlider.val( first ? min: max ).slider( \"refresh\" );\n\t\t\t\t\t$.data( otherSlider.get(0), \"mobile-slider\" ).handle.focus();\n\t\t\t\t\tself._sliderFirst.css( \"z-index\", first ? \"\" : 1 );\n\t\t\t\t\tself._trigger( \"normalize\" );\n\t\t\t\t}, 0 );\n\t\t\t\tthis._proxy = ( first ) ? \"first\" : \"last\";\n\t\t\t}\n\t\t\t//fixes issue where when both _sliders are at min they cannot be adjusted\n\t\t\tif ( min === max ) {\n\t\t\t\t$.data( thisSlider.get(0), \"mobile-slider\" ).handle.css( \"z-index\", 1 );\n\t\t\t\t$.data( otherSlider.get(0), \"mobile-slider\" ).handle.css( \"z-index\", 0 );\n\t\t\t} else {\n\t\t\t\t$.data( otherSlider.get(0), \"mobile-slider\" ).handle.css( \"z-index\", \"\" );\n\t\t\t\t$.data( thisSlider.get(0), \"mobile-slider\" ).handle.css( \"z-index\", \"\" );\n\t\t\t}\n\n\t\t\tthis._updateHighlight();\n\n\t\t\tif ( min >= max ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\t_updateHighlight: function() {\n\t\t\tvar min = parseInt( $.data( this._inputFirst.get(0), \"mobile-slider\" ).handle.get(0).style.left, 10 ),\n\t\t\t\tmax = parseInt( $.data( this._inputLast.get(0), \"mobile-slider\" ).handle.get(0).style.left, 10 ),\n\t\t\t\twidth = (max - min);\n\n\t\t\tthis.element.find( \".ui-slider-bg\" ).css({\n\t\t\t\t\"margin-left\": min + \"%\",\n\t\t\t\t\"width\": width + \"%\"\n\t\t\t});\n\t\t},\n\n\t\t_setTheme: function( value ) {\n\t\t\tthis._inputFirst.slider( \"option\", \"theme\", value );\n\t\t\tthis._inputLast.slider( \"option\", \"theme\", value );\n\t\t},\n\n\t\t_setTrackTheme: function( value ) {\n\t\t\tthis._inputFirst.slider( \"option\", \"trackTheme\", value );\n\t\t\tthis._inputLast.slider( \"option\", \"trackTheme\", value );\n\t\t},\n\n\t\t_setMini: function( value ) {\n\t\t\tthis._inputFirst.slider( \"option\", \"mini\", value );\n\t\t\tthis._inputLast.slider( \"option\", \"mini\", value );\n\t\t\tthis.element.toggleClass( \"ui-mini\", !!value );\n\t\t},\n\n\t\t_setHighlight: function( value ) {\n\t\t\tthis._inputFirst.slider( \"option\", \"highlight\", value );\n\t\t\tthis._inputLast.slider( \"option\", \"highlight\", value );\n\t\t},\n\n\t\t_setDisabled: function( value ) {\n\t\t\tthis._inputFirst.prop( \"disabled\", value );\n\t\t\tthis._inputLast.prop( \"disabled\", value );\n\t\t},\n\n\t\t_destroy: function() {\n\t\t\tthis._label.prependTo( this.element );\n\t\t\tthis.element.removeClass( \"ui-rangeslider ui-mini\" );\n\t\t\tthis._inputFirst.after( this._sliderFirst );\n\t\t\tthis._inputLast.after( this._sliderLast );\n\t\t\tthis._sliders.remove();\n\t\t\tthis.element.find( \"input\" ).removeClass( \"ui-rangeslider-first ui-rangeslider-last\" ).slider( \"destroy\" );\n\t\t}\n\n\t}, $.mobile.behaviors.formReset ) );\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n\t$.widget( \"mobile.textinput\", $.mobile.textinput, {\n\t\toptions: {\n\t\t\tclearBtn: false,\n\t\t\tclearBtnText: \"Clear text\"\n\t\t},\n\n\t\t_create: function() {\n\t\t\tthis._super();\n\n\t\t\tif ( this.isSearch ) {\n\t\t\t\tthis.options.clearBtn = true;\n\t\t\t}\n\n\t\t\tif ( !!this.options.clearBtn && this.inputNeedsWrap ) {\n\t\t\t\tthis._addClearBtn();\n\t\t\t}\n\t\t},\n\n\t\tclearButton: function() {\n\t\t\treturn $( \"<a href='#' tabindex='-1' aria-hidden='true' \" +\n\t\t\t\t\"class='ui-input-clear ui-btn ui-icon-delete ui-btn-icon-notext ui-corner-all'>\" +\n\t\t\t\t\"</a>\" )\n\t\t\t\t\t.attr( \"title\", this.options.clearBtnText )\n\t\t\t\t\t.text( this.options.clearBtnText );\n\t\t},\n\n\t\t_clearBtnClick: function( event ) {\n\t\t\tthis.element.val( \"\" )\n\t\t\t\t\t.focus()\n\t\t\t\t\t.trigger( \"change\" );\n\n\t\t\tthis._clearBtn.addClass( \"ui-input-clear-hidden\" );\n\t\t\tevent.preventDefault();\n\t\t},\n\n\t\t_addClearBtn: function() {\n\n\t\t\tif ( !this.options.enhanced ) {\n\t\t\t\tthis._enhanceClear();\n\t\t\t}\n\n\t\t\t$.extend( this, {\n\t\t\t\t_clearBtn: this.widget().find(\"a.ui-input-clear\")\n\t\t\t});\n\n\t\t\tthis._bindClearEvents();\n\n\t\t\tthis._toggleClear();\n\n\t\t},\n\n\t\t_enhanceClear: function() {\n\n\t\t\tthis.clearButton().appendTo( this.widget() );\n\t\t\tthis.widget().addClass( \"ui-input-has-clear\" );\n\n\t\t},\n\n\t\t_bindClearEvents: function() {\n\n\t\t\tthis._on( this._clearBtn, {\n\t\t\t\t\"click\": \"_clearBtnClick\"\n\t\t\t});\n\n\t\t\tthis._on({\n\t\t\t\t\"keyup\": \"_toggleClear\",\n\t\t\t\t\"change\": \"_toggleClear\",\n\t\t\t\t\"input\": \"_toggleClear\",\n\t\t\t\t\"focus\": \"_toggleClear\",\n\t\t\t\t\"blur\": \"_toggleClear\",\n\t\t\t\t\"cut\": \"_toggleClear\",\n\t\t\t\t\"paste\": \"_toggleClear\"\n\n\t\t\t});\n\n\t\t},\n\n\t\t_unbindClear: function() {\n\t\t\tthis._off( this._clearBtn, \"click\");\n\t\t\tthis._off( this.element, \"keyup change input focus blur cut paste\" );\n\t\t},\n\n\t\t_setOptions: function( options ) {\n\t\t\tthis._super( options );\n\n\t\t\tif ( options.clearBtn !== undefined &&\n\t\t\t\t!this.element.is( \"textarea, :jqmData(type='range')\" ) ) {\n\t\t\t\tif ( options.clearBtn ) {\n\t\t\t\t\tthis._addClearBtn();\n\t\t\t\t} else {\n\t\t\t\t\tthis._destroyClear();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( options.clearBtnText !== undefined && this._clearBtn !== undefined ) {\n\t\t\t\tthis._clearBtn.text( options.clearBtnText )\n\t\t\t\t\t.attr(\"title\", options.clearBtnText);\n\t\t\t}\n\t\t},\n\n\t\t_toggleClear: function() {\n\t\t\tthis._delay( \"_toggleClearClass\", 0 );\n\t\t},\n\n\t\t_toggleClearClass: function() {\n\t\t\tthis._clearBtn.toggleClass( \"ui-input-clear-hidden\", !this.element.val() );\n\t\t},\n\n\t\t_destroyClear: function() {\n\t\t\tthis.widget().removeClass( \"ui-input-has-clear\" );\n\t\t\tthis._unbindClear();\n\t\t\tthis._clearBtn.remove();\n\t\t},\n\n\t\t_destroy: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.clearBtn ) {\n\t\t\t\tthis._destroyClear();\n\t\t\t}\n\t\t}\n\n\t});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n\t$.widget( \"mobile.textinput\", $.mobile.textinput, {\n\t\toptions: {\n\t\t\tautogrow:true,\n\t\t\tkeyupTimeoutBuffer: 100\n\t\t},\n\n\t\t_create: function() {\n\t\t\tthis._super();\n\n\t\t\tif ( this.options.autogrow && this.isTextarea ) {\n\t\t\t\tthis._autogrow();\n\t\t\t}\n\t\t},\n\n\t\t_autogrow: function() {\n\t\t\tthis.element.addClass( \"ui-textinput-autogrow\" );\n\n\t\t\tthis._on({\n\t\t\t\t\"keyup\": \"_timeout\",\n\t\t\t\t\"change\": \"_timeout\",\n\t\t\t\t\"input\": \"_timeout\",\n\t\t\t\t\"paste\": \"_timeout\"\n\t\t\t});\n\n\t\t\t// Attach to the various you-have-become-visible notifications that the\n\t\t\t// various framework elements emit.\n\t\t\t// TODO: Remove all but the updatelayout handler once #6426 is fixed.\n\t\t\tthis._on( true, this.document, {\n\n\t\t\t\t// TODO: Move to non-deprecated event\n\t\t\t\t\"pageshow\": \"_handleShow\",\n\t\t\t\t\"popupbeforeposition\": \"_handleShow\",\n\t\t\t\t\"updatelayout\": \"_handleShow\",\n\t\t\t\t\"panelopen\": \"_handleShow\"\n\t\t\t});\n\t\t},\n\n\t\t// Synchronously fix the widget height if this widget's parents are such\n\t\t// that they show/hide content at runtime. We still need to check whether\n\t\t// the widget is actually visible in case it is contained inside multiple\n\t\t// such containers. For example: panel contains collapsible contains\n\t\t// autogrow textinput. The panel may emit \"panelopen\" indicating that its\n\t\t// content has become visible, but the collapsible is still collapsed, so\n\t\t// the autogrow textarea is still not visible.\n\t\t_handleShow: function( event ) {\n\t\t\tif ( $.contains( event.target, this.element[ 0 ] ) &&\n\t\t\t\tthis.element.is( \":visible\" ) ) {\n\n\t\t\t\tif ( event.type !== \"popupbeforeposition\" ) {\n\t\t\t\t\tthis.element\n\t\t\t\t\t\t.addClass( \"ui-textinput-autogrow-resize\" )\n\t\t\t\t\t\t.animationComplete(\n\t\t\t\t\t\t\t$.proxy( function() {\n\t\t\t\t\t\t\t\tthis.element.removeClass( \"ui-textinput-autogrow-resize\" );\n\t\t\t\t\t\t\t}, this ),\n\t\t\t\t\t\t\"transition\" );\n\t\t\t\t}\n\t\t\t\tthis._prepareHeightUpdate();\n\t\t\t}\n\t\t},\n\n\t\t_unbindAutogrow: function() {\n\t\t\tthis.element.removeClass( \"ui-textinput-autogrow\" );\n\t\t\tthis._off( this.element, \"keyup change input paste\" );\n\t\t\tthis._off( this.document,\n\t\t\t\t\"pageshow popupbeforeposition updatelayout panelopen\" );\n\t\t},\n\n\t\tkeyupTimeout: null,\n\n\t\t_prepareHeightUpdate: function( delay ) {\n\t\t\tif ( this.keyupTimeout ) {\n\t\t\t\tclearTimeout( this.keyupTimeout );\n\t\t\t}\n\t\t\tif ( delay === undefined ) {\n\t\t\t\tthis._updateHeight();\n\t\t\t} else {\n\t\t\t\tthis.keyupTimeout = this._delay( \"_updateHeight\", delay );\n\t\t\t}\n\t\t},\n\n\t\t_timeout: function() {\n\t\t\tthis._prepareHeightUpdate( this.options.keyupTimeoutBuffer );\n\t\t},\n\n\t\t_updateHeight: function() {\n\t\t\tvar paddingTop, paddingBottom, paddingHeight, scrollHeight, clientHeight,\n\t\t\t\tborderTop, borderBottom, borderHeight, height,\n\t\t\t\tscrollTop = this.window.scrollTop();\n\t\t\tthis.keyupTimeout = 0;\n\n\t\t\t// IE8 textareas have the onpage property - others do not\n\t\t\tif ( !( \"onpage\" in this.element[ 0 ] ) ) {\n\t\t\t\tthis.element.css({\n\t\t\t\t\t\"height\": 0,\n\t\t\t\t\t\"min-height\": 0,\n\t\t\t\t\t\"max-height\": 0\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tscrollHeight = this.element[ 0 ].scrollHeight;\n\t\t\tclientHeight = this.element[ 0 ].clientHeight;\n\t\t\tborderTop = parseFloat( this.element.css( \"border-top-width\" ) );\n\t\t\tborderBottom = parseFloat( this.element.css( \"border-bottom-width\" ) );\n\t\t\tborderHeight = borderTop + borderBottom;\n\t\t\theight = scrollHeight + borderHeight + 15;\n\n\t\t\t// Issue 6179: Padding is not included in scrollHeight and\n\t\t\t// clientHeight by Firefox if no scrollbar is visible. Because\n\t\t\t// textareas use the border-box box-sizing model, padding should be\n\t\t\t// included in the new (assigned) height. Because the height is set\n\t\t\t// to 0, clientHeight == 0 in Firefox. Therefore, we can use this to\n\t\t\t// check if padding must be added.\n\t\t\tif ( clientHeight === 0 ) {\n\t\t\t\tpaddingTop = parseFloat( this.element.css( \"padding-top\" ) );\n\t\t\t\tpaddingBottom = parseFloat( this.element.css( \"padding-bottom\" ) );\n\t\t\t\tpaddingHeight = paddingTop + paddingBottom;\n\n\t\t\t\theight += paddingHeight;\n\t\t\t}\n\n\t\t\tthis.element.css({\n\t\t\t\t\"height\": height,\n\t\t\t\t\"min-height\": \"\",\n\t\t\t\t\"max-height\": \"\"\n\t\t\t});\n\n\t\t\tthis.window.scrollTop( scrollTop );\n\t\t},\n\n\t\trefresh: function() {\n\t\t\tif ( this.options.autogrow && this.isTextarea ) {\n\t\t\t\tthis._updateHeight();\n\t\t\t}\n\t\t},\n\n\t\t_setOptions: function( options ) {\n\n\t\t\tthis._super( options );\n\n\t\t\tif ( options.autogrow !== undefined && this.isTextarea ) {\n\t\t\t\tif ( options.autogrow ) {\n\t\t\t\t\tthis._autogrow();\n\t\t\t\t} else {\n\t\t\t\t\tthis._unbindAutogrow();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t});\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.selectmenu\", $.extend( {\n\tinitSelector: \"select:not( :jqmData(role='slider')):not( :jqmData(role='flipswitch') )\",\n\n\toptions: {\n\t\ttheme: null,\n\t\ticon: \"carat-d\",\n\t\ticonpos: \"right\",\n\t\tinline: false,\n\t\tcorners: true,\n\t\tshadow: true,\n\t\ticonshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */\n\t\toverlayTheme: null,\n\t\tdividerTheme: null,\n\t\thidePlaceholderMenuItems: true,\n\t\tcloseText: \"Close\",\n\t\tnativeMenu: true,\n\t\t// This option defaults to true on iOS devices.\n\t\tpreventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( \"AppleWebKit\" ) > -1,\n\t\tmini: false\n\t},\n\n\t_button: function() {\n\t\treturn $( \"<div/>\" );\n\t},\n\n\t_setDisabled: function( value ) {\n\t\tthis.element.attr( \"disabled\", value );\n\t\tthis.button.attr( \"aria-disabled\", value );\n\t\treturn this._setOption( \"disabled\", value );\n\t},\n\n\t_focusButton : function() {\n\t\tvar self = this;\n\n\t\tsetTimeout( function() {\n\t\t\tself.button.focus();\n\t\t}, 40);\n\t},\n\n\t_selectOptions: function() {\n\t\treturn this.select.find( \"option\" );\n\t},\n\n\t// setup items that are generally necessary for select menu extension\n\t_preExtension: function() {\n\t\tvar inline = this.options.inline || this.element.jqmData( \"inline\" ),\n\t\t\tmini = this.options.mini || this.element.jqmData( \"mini\" ),\n\t\t\tclasses = \"\";\n\t\t// TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577\n\t\t/* if ( $el[0].className.length ) {\n\t\t\tclasses = $el[0].className;\n\t\t} */\n\t\tif ( !!~this.element[0].className.indexOf( \"ui-btn-left\" ) ) {\n\t\t\tclasses = \" ui-btn-left\";\n\t\t}\n\n\t\tif (  !!~this.element[0].className.indexOf( \"ui-btn-right\" ) ) {\n\t\t\tclasses = \" ui-btn-right\";\n\t\t}\n\n\t\tif ( inline ) {\n\t\t\tclasses += \" ui-btn-inline\";\n\t\t}\n\t\tif ( mini ) {\n\t\t\tclasses += \" ui-mini\";\n\t\t}\n\n\t\tthis.select = this.element.removeClass( \"ui-btn-left ui-btn-right\" ).wrap( \"<div class='ui-select\" + classes + \"'>\" );\n\t\tthis.selectId  = this.select.attr( \"id\" ) || ( \"select-\" + this.uuid );\n\t\tthis.buttonId = this.selectId + \"-button\";\n\t\tthis.label = $( \"label[for='\"+ this.selectId +\"']\" );\n\t\tthis.isMultiple = this.select[ 0 ].multiple;\n\t},\n\n\t_destroy: function() {\n\t\tvar wrapper = this.element.parents( \".ui-select\" );\n\t\tif ( wrapper.length > 0 ) {\n\t\t\tif ( wrapper.is( \".ui-btn-left, .ui-btn-right\" ) ) {\n\t\t\t\tthis.element.addClass( wrapper.hasClass( \"ui-btn-left\" ) ? \"ui-btn-left\" : \"ui-btn-right\" );\n\t\t\t}\n\t\t\tthis.element.insertAfter( wrapper );\n\t\t\twrapper.remove();\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tthis._preExtension();\n\n\t\tthis.button = this._button();\n\n\t\tvar self = this,\n\n\t\t\toptions = this.options,\n\n\t\t\ticonpos = options.icon ? ( options.iconpos || this.select.jqmData( \"iconpos\" ) ) : false,\n\n\t\t\tbutton = this.button\n\t\t\t\t.insertBefore( this.select )\n\t\t\t\t.attr( \"id\", this.buttonId )\n\t\t\t\t.addClass( \"ui-btn\" +\n\t\t\t\t\t( options.icon ? ( \" ui-icon-\" + options.icon + \" ui-btn-icon-\" + iconpos +\n\t\t\t\t\t( options.iconshadow ? \" ui-shadow-icon\" : \"\" ) ) :\t\"\" ) + /* TODO: Remove in 1.5. */\n\t\t\t\t\t( options.theme ? \" ui-btn-\" + options.theme : \"\" ) +\n\t\t\t\t\t( options.corners ? \" ui-corner-all\" : \"\" ) +\n\t\t\t\t\t( options.shadow ? \" ui-shadow\" : \"\" ) );\n\n\t\tthis.setButtonText();\n\n\t\t// Opera does not properly support opacity on select elements\n\t\t// In Mini, it hides the element, but not its text\n\t\t// On the desktop,it seems to do the opposite\n\t\t// for these reasons, using the nativeMenu option results in a full native select in Opera\n\t\tif ( options.nativeMenu && window.opera && window.opera.version ) {\n\t\t\tbutton.addClass( \"ui-select-nativeonly\" );\n\t\t}\n\n\t\t// Add counter for multi selects\n\t\tif ( this.isMultiple ) {\n\t\t\tthis.buttonCount = $( \"<span>\" )\n\t\t\t\t.addClass( \"ui-li-count ui-body-inherit\" )\n\t\t\t\t.hide()\n\t\t\t\t.appendTo( button.addClass( \"ui-li-has-count\" ) );\n\t\t}\n\n\t\t// Disable if specified\n\t\tif ( options.disabled || this.element.attr( \"disabled\" )) {\n\t\t\tthis.disable();\n\t\t}\n\n\t\t// Events on native select\n\t\tthis.select.change(function() {\n\t\t\tself.refresh();\n\n\t\t\tif ( !!options.nativeMenu ) {\n\t\t\t\tself._delay( function() {\n\t\t\t\t\tself.select.blur();\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tthis._handleFormReset();\n\n\t\tthis._on( this.button, {\n\t\t\tkeydown: \"_handleKeydown\"\n\t\t});\n\n\t\tthis.build();\n\t},\n\n\tbuild: function() {\n\t\tvar self = this;\n\n\t\tthis.select\n\t\t\t.appendTo( self.button )\n\t\t\t.bind( \"vmousedown\", function() {\n\t\t\t\t// Add active class to button\n\t\t\t\tself.button.addClass( $.mobile.activeBtnClass );\n\t\t\t})\n\t\t\t.bind( \"focus\", function() {\n\t\t\t\tself.button.addClass( $.mobile.focusClass );\n\t\t\t})\n\t\t\t.bind( \"blur\", function() {\n\t\t\t\tself.button.removeClass( $.mobile.focusClass );\n\t\t\t})\n\t\t\t.bind( \"focus vmouseover\", function() {\n\t\t\t\tself.button.trigger( \"vmouseover\" );\n\t\t\t})\n\t\t\t.bind( \"vmousemove\", function() {\n\t\t\t\t// Remove active class on scroll/touchmove\n\t\t\t\tself.button.removeClass( $.mobile.activeBtnClass );\n\t\t\t})\n\t\t\t.bind( \"change blur vmouseout\", function() {\n\t\t\t\tself.button.trigger( \"vmouseout\" )\n\t\t\t\t\t.removeClass( $.mobile.activeBtnClass );\n\t\t\t});\n\n\t\t// In many situations, iOS will zoom into the select upon tap, this prevents that from happening\n\t\tself.button.bind( \"vmousedown\", function() {\n\t\t\tif ( self.options.preventFocusZoom ) {\n\t\t\t\t\t$.mobile.zoom.disable( true );\n\t\t\t}\n\t\t});\n\t\tself.label.bind( \"click focus\", function() {\n\t\t\tif ( self.options.preventFocusZoom ) {\n\t\t\t\t\t$.mobile.zoom.disable( true );\n\t\t\t}\n\t\t});\n\t\tself.select.bind( \"focus\", function() {\n\t\t\tif ( self.options.preventFocusZoom ) {\n\t\t\t\t\t$.mobile.zoom.disable( true );\n\t\t\t}\n\t\t});\n\t\tself.button.bind( \"mouseup\", function() {\n\t\t\tif ( self.options.preventFocusZoom ) {\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t$.mobile.zoom.enable( true );\n\t\t\t\t}, 0 );\n\t\t\t}\n\t\t});\n\t\tself.select.bind( \"blur\", function() {\n\t\t\tif ( self.options.preventFocusZoom ) {\n\t\t\t\t$.mobile.zoom.enable( true );\n\t\t\t}\n\t\t});\n\n\t},\n\n\tselected: function() {\n\t\treturn this._selectOptions().filter( \":selected\" );\n\t},\n\n\tselectedIndices: function() {\n\t\tvar self = this;\n\n\t\treturn this.selected().map(function() {\n\t\t\treturn self._selectOptions().index( this );\n\t\t}).get();\n\t},\n\n\tsetButtonText: function() {\n\t\tvar self = this,\n\t\t\tselected = this.selected(),\n\t\t\ttext = this.placeholder,\n\t\t\tspan = $( document.createElement( \"span\" ) );\n\n\t\tthis.button.children( \"span\" ).not( \".ui-li-count\" ).remove().end().end().prepend( (function() {\n\t\t\tif ( selected.length ) {\n\t\t\t\ttext = selected.map(function() {\n\t\t\t\t\treturn $( this ).text();\n\t\t\t\t}).get().join( \", \" );\n\t\t\t} else {\n\t\t\t\ttext = self.placeholder;\n\t\t\t}\n\n\t\t\tif ( text ) {\n\t\t\t\tspan.text( text );\n\t\t\t} else {\n\n\t\t\t\t// Set the contents to &nbsp; which we write as &#160; to be XHTML compliant - see gh-6699\n\t\t\t\tspan.html( \"&#160;\" );\n\t\t\t}\n\n\t\t\t// TODO possibly aggregate multiple select option classes\n\t\t\treturn span\n\t\t\t\t.addClass( self.select.attr( \"class\" ) )\n\t\t\t\t.addClass( selected.attr( \"class\" ) )\n\t\t\t\t.removeClass( \"ui-screen-hidden\" );\n\t\t})());\n\t},\n\n\tsetButtonCount: function() {\n\t\tvar selected = this.selected();\n\n\t\t// multiple count inside button\n\t\tif ( this.isMultiple ) {\n\t\t\tthis.buttonCount[ selected.length > 1 ? \"show\" : \"hide\" ]().text( selected.length );\n\t\t}\n\t},\n\n\t_handleKeydown: function( /* event */ ) {\n\t\tthis._delay( \"_refreshButton\" );\n\t},\n\n\t_reset: function() {\n\t\tthis.refresh();\n\t},\n\n\t_refreshButton: function() {\n\t\tthis.setButtonText();\n\t\tthis.setButtonCount();\n\t},\n\n\trefresh: function() {\n\t\tthis._refreshButton();\n\t},\n\n\t// open and close preserved in native selects\n\t// to simplify users code when looping over selects\n\topen: $.noop,\n\tclose: $.noop,\n\n\tdisable: function() {\n\t\tthis._setDisabled( true );\n\t\tthis.button.addClass( \"ui-state-disabled\" );\n\t},\n\n\tenable: function() {\n\t\tthis._setDisabled( false );\n\t\tthis.button.removeClass( \"ui-state-disabled\" );\n\t}\n}, $.mobile.behaviors.formReset ) );\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.mobile.links = function( target ) {\n\n\t//links within content areas, tests included with page\n\t$( target )\n\t\t.find( \"a\" )\n\t\t.jqmEnhanceable()\n\t\t.filter( \":jqmData(rel='popup')[href][href!='']\" )\n\t\t.each( function() {\n\t\t\t// Accessibility info for popups\n\t\t\tvar element = this,\n\t\t\t\tidref = element.getAttribute( \"href\" ).substring( 1 );\n\n\t\t\tif ( idref ) {\n\t\t\t\telement.setAttribute( \"aria-haspopup\", true );\n\t\t\t\telement.setAttribute( \"aria-owns\", idref );\n\t\t\t\telement.setAttribute( \"aria-expanded\", false );\n\t\t\t}\n\t\t})\n\t\t.end()\n\t\t.not( \".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')\" )\n\t\t.addClass( \"ui-link\" );\n\n};\n\n})( jQuery );\n\n\n(function( $, undefined ) {\n\nfunction fitSegmentInsideSegment( windowSize, segmentSize, offset, desired ) {\n\tvar returnValue = desired;\n\n\tif ( windowSize < segmentSize ) {\n\t\t// Center segment if it's bigger than the window\n\t\treturnValue = offset + ( windowSize - segmentSize ) / 2;\n\t} else {\n\t\t// Otherwise center it at the desired coordinate while keeping it completely inside the window\n\t\treturnValue = Math.min( Math.max( offset, desired - segmentSize / 2 ), offset + windowSize - segmentSize );\n\t}\n\n\treturn returnValue;\n}\n\nfunction getWindowCoordinates( theWindow ) {\n\treturn {\n\t\tx: theWindow.scrollLeft(),\n\t\ty: theWindow.scrollTop(),\n\t\tcx: ( theWindow[ 0 ].innerWidth || theWindow.width() ),\n\t\tcy: ( theWindow[ 0 ].innerHeight || theWindow.height() )\n\t};\n}\n\n$.widget( \"mobile.popup\", {\n\toptions: {\n\t\twrapperClass: null,\n\t\ttheme: null,\n\t\toverlayTheme: null,\n\t\tshadow: true,\n\t\tcorners: true,\n\t\ttransition: \"none\",\n\t\tpositionTo: \"origin\",\n\t\ttolerance: null,\n\t\tcloseLinkSelector: \"a:jqmData(rel='back')\",\n\t\tcloseLinkEvents: \"click.popup\",\n\t\tnavigateEvents: \"navigate.popup\",\n\t\tcloseEvents: \"navigate.popup pagebeforechange.popup\",\n\t\tdismissible: true,\n\t\tenhanced: false,\n\n\t\t// NOTE Windows Phone 7 has a scroll position caching issue that\n\t\t//      requires us to disable popup history management by default\n\t\t//      https://github.com/jquery/jquery-mobile/issues/4784\n\t\t//\n\t\t// NOTE this option is modified in _create!\n\t\thistory: !$.mobile.browser.oldIE\n\t},\n\n\t// When the user depresses the mouse/finger on an element inside the popup while the popup is\n\t// open, we ignore resize events for a short while. This prevents #6961.\n\t_handleDocumentVmousedown: function( theEvent ) {\n\t\tif ( this._isOpen && $.contains( this._ui.container[ 0 ], theEvent.target ) ) {\n\t\t\tthis._ignoreResizeEvents();\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tvar theElement = this.element,\n\t\t\tmyId = theElement.attr( \"id\" ),\n\t\t\tcurrentOptions = this.options;\n\n\t\t// We need to adjust the history option to be false if there's no AJAX nav.\n\t\t// We can't do it in the option declarations because those are run before\n\t\t// it is determined whether there shall be AJAX nav.\n\t\tcurrentOptions.history = currentOptions.history && $.mobile.ajaxEnabled && $.mobile.hashListeningEnabled;\n\n\t\tthis._on( this.document, {\n\t\t\t\"vmousedown\": \"_handleDocumentVmousedown\"\n\t\t});\n\n\t\t// Define instance variables\n\t\t$.extend( this, {\n\t\t\t_scrollTop: 0,\n\t\t\t_page: theElement.closest( \".ui-page\" ),\n\t\t\t_ui: null,\n\t\t\t_fallbackTransition: \"\",\n\t\t\t_currentTransition: false,\n\t\t\t_prerequisites: null,\n\t\t\t_isOpen: false,\n\t\t\t_tolerance: null,\n\t\t\t_resizeData: null,\n\t\t\t_ignoreResizeTo: 0,\n\t\t\t_orientationchangeInProgress: false\n\t\t});\n\n\t\tif ( this._page.length === 0 ) {\n\t\t\tthis._page = $( \"body\" );\n\t\t}\n\n\t\tif ( currentOptions.enhanced ) {\n\t\t\tthis._ui = {\n\t\t\t\tcontainer: theElement.parent(),\n\t\t\t\tscreen: theElement.parent().prev(),\n\t\t\t\tplaceholder: $( this.document[ 0 ].getElementById( myId + \"-placeholder\" ) )\n\t\t\t};\n\t\t} else {\n\t\t\tthis._ui = this._enhance( theElement, myId );\n\t\t\tthis._applyTransition( currentOptions.transition );\n\t\t}\n\t\tthis\n\t\t\t._setTolerance( currentOptions.tolerance )\n\t\t\t._ui.focusElement = this._ui.container;\n\n\t\t// Event handlers\n\t\tthis._on( this._ui.screen, { \"vclick\": \"_eatEventAndClose\" } );\n\t\tthis._on( this.window, {\n\t\t\torientationchange: $.proxy( this, \"_handleWindowOrientationchange\" ),\n\t\t\tresize: $.proxy( this, \"_handleWindowResize\" ),\n\t\t\tkeyup: $.proxy( this, \"_handleWindowKeyUp\" )\n\t\t});\n\t\tthis._on( this.document, { \"focusin\": \"_handleDocumentFocusIn\" } );\n\t},\n\n\t_enhance: function( theElement, myId ) {\n\t\tvar currentOptions = this.options,\n\t\t\twrapperClass = currentOptions.wrapperClass,\n\t\t\tui = {\n\t\t\t\tscreen: $( \"<div class='ui-screen-hidden ui-popup-screen \" +\n\t\t\t\tthis._themeClassFromOption( \"ui-overlay-\", currentOptions.overlayTheme ) + \"'></div>\" ),\n\t\t\t\tplaceholder: $( \"<div style='display: none;'><!-- placeholder --></div>\" ),\n\t\t\t\tcontainer: $( \"<div class='ui-popup-container ui-popup-hidden ui-popup-truncate\" +\n\t\t\t\t\t( wrapperClass ? ( \" \" + wrapperClass ) : \"\" ) + \"'></div>\" )\n\t\t\t},\n\t\t\tfragment = this.document[ 0 ].createDocumentFragment();\n\n\t\tfragment.appendChild( ui.screen[ 0 ] );\n\t\tfragment.appendChild( ui.container[ 0 ] );\n\n\t\tif ( myId ) {\n\t\t\tui.screen.attr( \"id\", myId + \"-screen\" );\n\t\t\tui.container.attr( \"id\", myId + \"-popup\" );\n\t\t\tui.placeholder\n\t\t\t\t.attr( \"id\", myId + \"-placeholder\" )\n\t\t\t\t.html( \"<!-- placeholder for \" + myId + \" -->\" );\n\t\t}\n\n\t\t// Apply the proto\n\t\tthis._page[ 0 ].appendChild( fragment );\n\t\t// Leave a placeholder where the element used to be\n\t\tui.placeholder.insertAfter( theElement );\n\t\ttheElement\n\t\t\t.detach()\n\t\t\t.addClass( \"ui-popup \" +\n\t\t\t\tthis._themeClassFromOption( \"ui-body-\", currentOptions.theme ) + \" \" +\n\t\t\t\t( currentOptions.shadow ? \"ui-overlay-shadow \" : \"\" ) +\n\t\t\t\t( currentOptions.corners ? \"ui-corner-all \" : \"\" ) )\n\t\t\t.appendTo( ui.container );\n\n\t\treturn ui;\n\t},\n\n\t_eatEventAndClose: function( theEvent ) {\n\t\ttheEvent.preventDefault();\n\t\ttheEvent.stopImmediatePropagation();\n\t\tif ( this.options.dismissible ) {\n\t\t\tthis.close();\n\t\t}\n\t\treturn false;\n\t},\n\n\t// Make sure the screen covers the entire document - CSS is sometimes not\n\t// enough to accomplish this.\n\t_resizeScreen: function() {\n\t\tvar screen = this._ui.screen,\n\t\t\tpopupHeight = this._ui.container.outerHeight( true ),\n\t\t\tscreenHeight = screen.removeAttr( \"style\" ).height(),\n\n\t\t\t// Subtracting 1 here is necessary for an obscure Andrdoid 4.0 bug where\n\t\t\t// the browser hangs if the screen covers the entire document :/\n\t\t\tdocumentHeight = this.document.height() - 1;\n\n\t\tif ( screenHeight < documentHeight ) {\n\t\t\tscreen.height( documentHeight );\n\t\t} else if ( popupHeight > screenHeight ) {\n\t\t\tscreen.height( popupHeight );\n\t\t}\n\t},\n\n\t_handleWindowKeyUp: function( theEvent ) {\n\t\tif ( this._isOpen && theEvent.keyCode === $.mobile.keyCode.ESCAPE ) {\n\t\t\treturn this._eatEventAndClose( theEvent );\n\t\t}\n\t},\n\n\t_expectResizeEvent: function() {\n\t\tvar windowCoordinates = getWindowCoordinates( this.window );\n\n\t\tif ( this._resizeData ) {\n\t\t\tif ( windowCoordinates.x === this._resizeData.windowCoordinates.x &&\n\t\t\t\twindowCoordinates.y === this._resizeData.windowCoordinates.y &&\n\t\t\t\twindowCoordinates.cx === this._resizeData.windowCoordinates.cx &&\n\t\t\t\twindowCoordinates.cy === this._resizeData.windowCoordinates.cy ) {\n\t\t\t\t// timeout not refreshed\n\t\t\t\treturn false;\n\t\t\t} else {\n\t\t\t\t// clear existing timeout - it will be refreshed below\n\t\t\t\tclearTimeout( this._resizeData.timeoutId );\n\t\t\t}\n\t\t}\n\n\t\tthis._resizeData = {\n\t\t\ttimeoutId: this._delay( \"_resizeTimeout\", 200 ),\n\t\t\twindowCoordinates: windowCoordinates\n\t\t};\n\n\t\treturn true;\n\t},\n\n\t_resizeTimeout: function() {\n\t\tif ( this._isOpen ) {\n\t\t\tif ( !this._expectResizeEvent() ) {\n\t\t\t\tif ( this._ui.container.hasClass( \"ui-popup-hidden\" ) ) {\n\t\t\t\t\t// effectively rapid-open the popup while leaving the screen intact\n\t\t\t\t\tthis._ui.container.removeClass( \"ui-popup-hidden ui-popup-truncate\" );\n\t\t\t\t\tthis.reposition( { positionTo: \"window\" } );\n\t\t\t\t\tthis._ignoreResizeEvents();\n\t\t\t\t}\n\n\t\t\t\tthis._resizeScreen();\n\t\t\t\tthis._resizeData = null;\n\t\t\t\tthis._orientationchangeInProgress = false;\n\t\t\t}\n\t\t} else {\n\t\t\tthis._resizeData = null;\n\t\t\tthis._orientationchangeInProgress = false;\n\t\t}\n\t},\n\n\t_stopIgnoringResizeEvents: function() {\n\t\tthis._ignoreResizeTo = 0;\n\t},\n\n\t_ignoreResizeEvents: function() {\n\t\tif ( this._ignoreResizeTo ) {\n\t\t\tclearTimeout( this._ignoreResizeTo );\n\t\t}\n\t\tthis._ignoreResizeTo = this._delay( \"_stopIgnoringResizeEvents\", 1000 );\n\t},\n\n\t_handleWindowResize: function(/* theEvent */) {\n\t\tif ( this._isOpen && this._ignoreResizeTo === 0 ) {\n\t\t\tif ( ( this._expectResizeEvent() || this._orientationchangeInProgress ) &&\n\t\t\t\t!this._ui.container.hasClass( \"ui-popup-hidden\" ) ) {\n\t\t\t\t// effectively rapid-close the popup while leaving the screen intact\n\t\t\t\tthis._ui.container\n\t\t\t\t\t.addClass( \"ui-popup-hidden ui-popup-truncate\" )\n\t\t\t\t\t.removeAttr( \"style\" );\n\t\t\t}\n\t\t}\n\t},\n\n\t_handleWindowOrientationchange: function(/* theEvent */) {\n\t\tif ( !this._orientationchangeInProgress && this._isOpen && this._ignoreResizeTo === 0 ) {\n\t\t\tthis._expectResizeEvent();\n\t\t\tthis._orientationchangeInProgress = true;\n\t\t}\n\t},\n\n\t// When the popup is open, attempting to focus on an element that is not a\n\t// child of the popup will redirect focus to the popup\n\t_handleDocumentFocusIn: function( theEvent ) {\n\t\tvar target,\n\t\t\ttargetElement = theEvent.target,\n\t\t\tui = this._ui;\n\n\t\tif ( !this._isOpen ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( targetElement !== ui.container[ 0 ] ) {\n\t\t\ttarget = $( targetElement );\n\t\t\tif ( !$.contains( ui.container[ 0 ], targetElement ) ) {\n\t\t\t\t$( this.document[ 0 ].activeElement ).one( \"focus\", $.proxy( function() {\n\t\t\t\t\tthis._safelyBlur( targetElement );\n\t\t\t\t}, this ) );\n\t\t\t\tui.focusElement.focus();\n\t\t\t\ttheEvent.preventDefault();\n\t\t\t\ttheEvent.stopImmediatePropagation();\n\t\t\t\treturn false;\n\t\t\t} else if ( ui.focusElement[ 0 ] === ui.container[ 0 ] ) {\n\t\t\t\tui.focusElement = target;\n\t\t\t}\n\t\t}\n\n\t\tthis._ignoreResizeEvents();\n\t},\n\n\t_themeClassFromOption: function( prefix, value ) {\n\t\treturn ( value ? ( value === \"none\" ? \"\" : ( prefix + value ) ) : ( prefix + \"inherit\" ) );\n\t},\n\n\t_applyTransition: function( value ) {\n\t\tif ( value ) {\n\t\t\tthis._ui.container.removeClass( this._fallbackTransition );\n\t\t\tif ( value !== \"none\" ) {\n\t\t\t\tthis._fallbackTransition = $.mobile._maybeDegradeTransition( value );\n\t\t\t\tif ( this._fallbackTransition === \"none\" ) {\n\t\t\t\t\tthis._fallbackTransition = \"\";\n\t\t\t\t}\n\t\t\t\tthis._ui.container.addClass( this._fallbackTransition );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOptions: function( newOptions ) {\n\t\tvar currentOptions = this.options,\n\t\t\ttheElement = this.element,\n\t\t\tscreen = this._ui.screen;\n\n\t\tif ( newOptions.wrapperClass !== undefined ) {\n\t\t\tthis._ui.container\n\t\t\t\t.removeClass( currentOptions.wrapperClass )\n\t\t\t\t.addClass( newOptions.wrapperClass );\n\t\t}\n\n\t\tif ( newOptions.theme !== undefined ) {\n\t\t\ttheElement\n\t\t\t\t.removeClass( this._themeClassFromOption( \"ui-body-\", currentOptions.theme ) )\n\t\t\t\t.addClass( this._themeClassFromOption( \"ui-body-\", newOptions.theme ) );\n\t\t}\n\n\t\tif ( newOptions.overlayTheme !== undefined ) {\n\t\t\tscreen\n\t\t\t\t.removeClass( this._themeClassFromOption( \"ui-overlay-\", currentOptions.overlayTheme ) )\n\t\t\t\t.addClass( this._themeClassFromOption( \"ui-overlay-\", newOptions.overlayTheme ) );\n\n\t\t\tif ( this._isOpen ) {\n\t\t\t\tscreen.addClass( \"in\" );\n\t\t\t}\n\t\t}\n\n\t\tif ( newOptions.shadow !== undefined ) {\n\t\t\ttheElement.toggleClass( \"ui-overlay-shadow\", newOptions.shadow );\n\t\t}\n\n\t\tif ( newOptions.corners !== undefined ) {\n\t\t\ttheElement.toggleClass( \"ui-corner-all\", newOptions.corners );\n\t\t}\n\n\t\tif ( newOptions.transition !== undefined ) {\n\t\t\tif ( !this._currentTransition ) {\n\t\t\t\tthis._applyTransition( newOptions.transition );\n\t\t\t}\n\t\t}\n\n\t\tif ( newOptions.tolerance !== undefined ) {\n\t\t\tthis._setTolerance( newOptions.tolerance );\n\t\t}\n\n\t\tif ( newOptions.disabled !== undefined ) {\n\t\t\tif ( newOptions.disabled ) {\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}\n\n\t\treturn this._super( newOptions );\n\t},\n\n\t_setTolerance: function( value ) {\n\t\tvar tol = { t: 30, r: 15, b: 30, l: 15 },\n\t\t\tar;\n\n\t\tif ( value !== undefined ) {\n\t\t\tar = String( value ).split( \",\" );\n\n\t\t\t$.each( ar, function( idx, val ) { ar[ idx ] = parseInt( val, 10 ); } );\n\n\t\t\tswitch( ar.length ) {\n\t\t\t\t// All values are to be the same\n\t\t\t\tcase 1:\n\t\t\t\t\tif ( !isNaN( ar[ 0 ] ) ) {\n\t\t\t\t\t\ttol.t = tol.r = tol.b = tol.l = ar[ 0 ];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t// The first value denotes top/bottom tolerance, and the second value denotes left/right tolerance\n\t\t\t\tcase 2:\n\t\t\t\t\tif ( !isNaN( ar[ 0 ] ) ) {\n\t\t\t\t\t\ttol.t = tol.b = ar[ 0 ];\n\t\t\t\t\t}\n\t\t\t\t\tif ( !isNaN( ar[ 1 ] ) ) {\n\t\t\t\t\t\ttol.l = tol.r = ar[ 1 ];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t// The array contains values in the order top, right, bottom, left\n\t\t\t\tcase 4:\n\t\t\t\t\tif ( !isNaN( ar[ 0 ] ) ) {\n\t\t\t\t\t\ttol.t = ar[ 0 ];\n\t\t\t\t\t}\n\t\t\t\t\tif ( !isNaN( ar[ 1 ] ) ) {\n\t\t\t\t\t\ttol.r = ar[ 1 ];\n\t\t\t\t\t}\n\t\t\t\t\tif ( !isNaN( ar[ 2 ] ) ) {\n\t\t\t\t\t\ttol.b = ar[ 2 ];\n\t\t\t\t\t}\n\t\t\t\t\tif ( !isNaN( ar[ 3 ] ) ) {\n\t\t\t\t\t\ttol.l = ar[ 3 ];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthis._tolerance = tol;\n\t\treturn this;\n\t},\n\n\t_clampPopupWidth: function( infoOnly ) {\n\t\tvar menuSize,\n\t\t\twindowCoordinates = getWindowCoordinates( this.window ),\n\t\t\t// rectangle within which the popup must fit\n\t\t\trectangle = {\n\t\t\t\tx: this._tolerance.l,\n\t\t\t\ty: windowCoordinates.y + this._tolerance.t,\n\t\t\t\tcx: windowCoordinates.cx - this._tolerance.l - this._tolerance.r,\n\t\t\t\tcy: windowCoordinates.cy - this._tolerance.t - this._tolerance.b\n\t\t\t};\n\n\t\tif ( !infoOnly ) {\n\t\t\t// Clamp the width of the menu before grabbing its size\n\t\t\tthis._ui.container.css( \"max-width\", rectangle.cx );\n\t\t}\n\n\t\tmenuSize = {\n\t\t\tcx: this._ui.container.outerWidth( true ),\n\t\t\tcy: this._ui.container.outerHeight( true )\n\t\t};\n\n\t\treturn { rc: rectangle, menuSize: menuSize };\n\t},\n\n\t_calculateFinalLocation: function( desired, clampInfo ) {\n\t\tvar returnValue,\n\t\t\trectangle = clampInfo.rc,\n\t\t\tmenuSize = clampInfo.menuSize;\n\n\t\t// Center the menu over the desired coordinates, while not going outside\n\t\t// the window tolerances. This will center wrt. the window if the popup is\n\t\t// too large.\n\t\treturnValue = {\n\t\t\tleft: fitSegmentInsideSegment( rectangle.cx, menuSize.cx, rectangle.x, desired.x ),\n\t\t\ttop: fitSegmentInsideSegment( rectangle.cy, menuSize.cy, rectangle.y, desired.y )\n\t\t};\n\n\t\t// Make sure the top of the menu is visible\n\t\treturnValue.top = Math.max( 0, returnValue.top );\n\n\t\t// If the height of the menu is smaller than the height of the document\n\t\t// align the bottom with the bottom of the document\n\n\t\treturnValue.top -= Math.min( returnValue.top,\n\t\t\tMath.max( 0, returnValue.top + menuSize.cy - this.document.height() ) );\n\n\t\treturn returnValue;\n\t},\n\n\t// Try and center the overlay over the given coordinates\n\t_placementCoords: function( desired ) {\n\t\treturn this._calculateFinalLocation( desired, this._clampPopupWidth() );\n\t},\n\n\t_createPrerequisites: function( screenPrerequisite, containerPrerequisite, whenDone ) {\n\t\tvar prerequisites,\n\t\t\tself = this;\n\n\t\t// It is important to maintain both the local variable prerequisites and\n\t\t// self._prerequisites. The local variable remains in the closure of the\n\t\t// functions which call the callbacks passed in. The comparison between the\n\t\t// local variable and self._prerequisites is necessary, because once a\n\t\t// function has been passed to .animationComplete() it will be called next\n\t\t// time an animation completes, even if that's not the animation whose end\n\t\t// the function was supposed to catch (for example, if an abort happens\n\t\t// during the opening animation, the .animationComplete handler is not\n\t\t// called for that animation anymore, but the handler remains attached, so\n\t\t// it is called the next time the popup is opened - making it stale.\n\t\t// Comparing the local variable prerequisites to the widget-level variable\n\t\t// self._prerequisites ensures that callbacks triggered by a stale\n\t\t// .animationComplete will be ignored.\n\n\t\tprerequisites = {\n\t\t\tscreen: $.Deferred(),\n\t\t\tcontainer: $.Deferred()\n\t\t};\n\n\t\tprerequisites.screen.then( function() {\n\t\t\tif ( prerequisites === self._prerequisites ) {\n\t\t\t\tscreenPrerequisite();\n\t\t\t}\n\t\t});\n\n\t\tprerequisites.container.then( function() {\n\t\t\tif ( prerequisites === self._prerequisites ) {\n\t\t\t\tcontainerPrerequisite();\n\t\t\t}\n\t\t});\n\n\t\t$.when( prerequisites.screen, prerequisites.container ).done( function() {\n\t\t\tif ( prerequisites === self._prerequisites ) {\n\t\t\t\tself._prerequisites = null;\n\t\t\t\twhenDone();\n\t\t\t}\n\t\t});\n\n\t\tself._prerequisites = prerequisites;\n\t},\n\n\t_animate: function( args ) {\n\t\t// NOTE before removing the default animation of the screen\n\t\t//      this had an animate callback that would resolve the deferred\n\t\t//      now the deferred is resolved immediately\n\t\t// TODO remove the dependency on the screen deferred\n\t\tthis._ui.screen\n\t\t\t.removeClass( args.classToRemove )\n\t\t\t.addClass( args.screenClassToAdd );\n\n\t\targs.prerequisites.screen.resolve();\n\n\t\tif ( args.transition && args.transition !== \"none\" ) {\n\t\t\tif ( args.applyTransition ) {\n\t\t\t\tthis._applyTransition( args.transition );\n\t\t\t}\n\t\t\tif ( this._fallbackTransition ) {\n\t\t\t\tthis._ui.container\n\t\t\t\t\t.addClass( args.containerClassToAdd )\n\t\t\t\t\t.removeClass( args.classToRemove )\n\t\t\t\t\t.animationComplete( $.proxy( args.prerequisites.container, \"resolve\" ) );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis._ui.container.removeClass( args.classToRemove );\n\t\targs.prerequisites.container.resolve();\n\t},\n\n\t// The desired coordinates passed in will be returned untouched if no reference element can be identified via\n\t// desiredPosition.positionTo. Nevertheless, this function ensures that its return value always contains valid\n\t// x and y coordinates by specifying the center middle of the window if the coordinates are absent.\n\t// options: { x: coordinate, y: coordinate, positionTo: string: \"origin\", \"window\", or jQuery selector\n\t_desiredCoords: function( openOptions ) {\n\t\tvar offset,\n\t\t\tdst = null,\n\t\t\twindowCoordinates = getWindowCoordinates( this.window ),\n\t\t\tx = openOptions.x,\n\t\t\ty = openOptions.y,\n\t\t\tpTo = openOptions.positionTo;\n\n\t\t// Establish which element will serve as the reference\n\t\tif ( pTo && pTo !== \"origin\" ) {\n\t\t\tif ( pTo === \"window\" ) {\n\t\t\t\tx = windowCoordinates.cx / 2 + windowCoordinates.x;\n\t\t\t\ty = windowCoordinates.cy / 2 + windowCoordinates.y;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tdst = $( pTo );\n\t\t\t\t} catch( err ) {\n\t\t\t\t\tdst = null;\n\t\t\t\t}\n\t\t\t\tif ( dst ) {\n\t\t\t\t\tdst.filter( \":visible\" );\n\t\t\t\t\tif ( dst.length === 0 ) {\n\t\t\t\t\t\tdst = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If an element was found, center over it\n\t\tif ( dst ) {\n\t\t\toffset = dst.offset();\n\t\t\tx = offset.left + dst.outerWidth() / 2;\n\t\t\ty = offset.top + dst.outerHeight() / 2;\n\t\t}\n\n\t\t// Make sure x and y are valid numbers - center over the window\n\t\tif ( $.type( x ) !== \"number\" || isNaN( x ) ) {\n\t\t\tx = windowCoordinates.cx / 2 + windowCoordinates.x;\n\t\t}\n\t\tif ( $.type( y ) !== \"number\" || isNaN( y ) ) {\n\t\t\ty = windowCoordinates.cy / 2 + windowCoordinates.y;\n\t\t}\n\n\t\treturn { x: x, y: y };\n\t},\n\n\t_reposition: function( openOptions ) {\n\t\t// We only care about position-related parameters for repositioning\n\t\topenOptions = {\n\t\t\tx: openOptions.x,\n\t\t\ty: openOptions.y,\n\t\t\tpositionTo: openOptions.positionTo\n\t\t};\n\t\tthis._trigger( \"beforeposition\", undefined, openOptions );\n\t\tthis._ui.container.offset( this._placementCoords( this._desiredCoords( openOptions ) ) );\n\t},\n\n\treposition: function( openOptions ) {\n\t\tif ( this._isOpen ) {\n\t\t\tthis._reposition( openOptions );\n\t\t}\n\t},\n\n\t_safelyBlur: function( currentElement ){\n\t\tif ( currentElement !== this.window[ 0 ] &&\n\t\t\tcurrentElement.nodeName.toLowerCase() !== \"body\" ) {\n\t\t\t\t$( currentElement ).blur();\n\t\t}\n\t},\n\n\t_openPrerequisitesComplete: function() {\n\t\tvar id = this.element.attr( \"id\" ),\n\t\t\tfirstFocus = this._ui.container.find( \":focusable\" ).first();\n\n\t\tthis._ui.container.addClass( \"ui-popup-active\" );\n\t\tthis._isOpen = true;\n\t\tthis._resizeScreen();\n\n\t\t// Check to see if currElement is not a child of the container.  If it's not, blur\n\t\tif ( !$.contains( this._ui.container[ 0 ], this.document[ 0 ].activeElement ) ) {\n\t\t\tthis._safelyBlur( this.document[ 0 ].activeElement );\n\t\t}\n\t\tif ( firstFocus.length > 0 ) {\n\t\t\tthis._ui.focusElement = firstFocus;\n\t\t}\n\t\tthis._ignoreResizeEvents();\n\t\tif ( id ) {\n\t\t\tthis.document.find( \"[aria-haspopup='true'][aria-owns='\" +  id + \"']\" ).attr( \"aria-expanded\", true );\n\t\t}\n\t\tthis._trigger( \"afteropen\" );\n\t},\n\n\t_open: function( options ) {\n\t\tvar openOptions = $.extend( {}, this.options, options ),\n\t\t\t// TODO move blacklist to private method\n\t\t\tandroidBlacklist = ( function() {\n\t\t\t\tvar ua = navigator.userAgent,\n\t\t\t\t\t// Rendering engine is Webkit, and capture major version\n\t\t\t\t\twkmatch = ua.match( /AppleWebKit\\/([0-9\\.]+)/ ),\n\t\t\t\t\twkversion = !!wkmatch && wkmatch[ 1 ],\n\t\t\t\t\tandroidmatch = ua.match( /Android (\\d+(?:\\.\\d+))/ ),\n\t\t\t\t\tandversion = !!androidmatch && androidmatch[ 1 ],\n\t\t\t\t\tchromematch = ua.indexOf( \"Chrome\" ) > -1;\n\n\t\t\t\t// Platform is Android, WebKit version is greater than 534.13 ( Android 3.2.1 ) and not Chrome.\n\t\t\t\tif ( androidmatch !== null && andversion === \"4.0\" && wkversion && wkversion > 534.13 && !chromematch ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}());\n\n\t\t// Count down to triggering \"popupafteropen\" - we have two prerequisites:\n\t\t// 1. The popup window animation completes (container())\n\t\t// 2. The screen opacity animation completes (screen())\n\t\tthis._createPrerequisites(\n\t\t\t$.noop,\n\t\t\t$.noop,\n\t\t\t$.proxy( this, \"_openPrerequisitesComplete\" ) );\n\n\t\tthis._currentTransition = openOptions.transition;\n\t\tthis._applyTransition( openOptions.transition );\n\n\t\tthis._ui.screen.removeClass( \"ui-screen-hidden\" );\n\t\tthis._ui.container.removeClass( \"ui-popup-truncate\" );\n\n\t\t// Give applications a chance to modify the contents of the container before it appears\n\t\tthis._reposition( openOptions );\n\n\t\tthis._ui.container.removeClass( \"ui-popup-hidden\" );\n\n\t\tif ( this.options.overlayTheme && androidBlacklist ) {\n\t\t\t/* TODO: The native browser on Android 4.0.X (\"Ice Cream Sandwich\") suffers from an issue where the popup overlay appears to be z-indexed above the popup itself when certain other styles exist on the same page -- namely, any element set to `position: fixed` and certain types of input. These issues are reminiscent of previously uncovered bugs in older versions of Android's native browser: https://github.com/scottjehl/Device-Bugs/issues/3\n\t\t\tThis fix closes the following bugs ( I use \"closes\" with reluctance, and stress that this issue should be revisited as soon as possible ):\n\t\t\thttps://github.com/jquery/jquery-mobile/issues/4816\n\t\t\thttps://github.com/jquery/jquery-mobile/issues/4844\n\t\t\thttps://github.com/jquery/jquery-mobile/issues/4874\n\t\t\t*/\n\n\t\t\t// TODO sort out why this._page isn't working\n\t\t\tthis.element.closest( \".ui-page\" ).addClass( \"ui-popup-open\" );\n\t\t}\n\t\tthis._animate({\n\t\t\tadditionalCondition: true,\n\t\t\ttransition: openOptions.transition,\n\t\t\tclassToRemove: \"\",\n\t\t\tscreenClassToAdd: \"in\",\n\t\t\tcontainerClassToAdd: \"in\",\n\t\t\tapplyTransition: false,\n\t\t\tprerequisites: this._prerequisites\n\t\t});\n\t},\n\n\t_closePrerequisiteScreen: function() {\n\t\tthis._ui.screen\n\t\t\t.removeClass( \"out\" )\n\t\t\t.addClass( \"ui-screen-hidden\" );\n\t},\n\n\t_closePrerequisiteContainer: function() {\n\t\tthis._ui.container\n\t\t\t.removeClass( \"reverse out\" )\n\t\t\t.addClass( \"ui-popup-hidden ui-popup-truncate\" )\n\t\t\t.removeAttr( \"style\" );\n\t},\n\n\t_closePrerequisitesDone: function() {\n\t\tvar container = this._ui.container,\n\t\t\tid = this.element.attr( \"id\" );\n\n\t\t// remove the global mutex for popups\n\t\t$.mobile.popup.active = undefined;\n\n\t\t// Blur elements inside the container, including the container\n\t\t$( \":focus\", container[ 0 ] ).add( container[ 0 ] ).blur();\n\n\t\tif ( id ) {\n\t\t\tthis.document.find( \"[aria-haspopup='true'][aria-owns='\" +  id + \"']\" ).attr( \"aria-expanded\", false );\n\t\t}\n\n\t\t// alert users that the popup is closed\n\t\tthis._trigger( \"afterclose\" );\n\t},\n\n\t_close: function( immediate ) {\n\t\tthis._ui.container.removeClass( \"ui-popup-active\" );\n\t\tthis._page.removeClass( \"ui-popup-open\" );\n\n\t\tthis._isOpen = false;\n\n\t\t// Count down to triggering \"popupafterclose\" - we have two prerequisites:\n\t\t// 1. The popup window reverse animation completes (container())\n\t\t// 2. The screen opacity animation completes (screen())\n\t\tthis._createPrerequisites(\n\t\t\t$.proxy( this, \"_closePrerequisiteScreen\" ),\n\t\t\t$.proxy( this, \"_closePrerequisiteContainer\" ),\n\t\t\t$.proxy( this, \"_closePrerequisitesDone\" ) );\n\n\t\tthis._animate( {\n\t\t\tadditionalCondition: this._ui.screen.hasClass( \"in\" ),\n\t\t\ttransition: ( immediate ? \"none\" : ( this._currentTransition ) ),\n\t\t\tclassToRemove: \"in\",\n\t\t\tscreenClassToAdd: \"out\",\n\t\t\tcontainerClassToAdd: \"reverse out\",\n\t\t\tapplyTransition: true,\n\t\t\tprerequisites: this._prerequisites\n\t\t});\n\t},\n\n\t_unenhance: function() {\n\t\tif ( this.options.enhanced ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Put the element back to where the placeholder was and remove the \"ui-popup\" class\n\t\tthis._setOptions( { theme: $.mobile.popup.prototype.options.theme } );\n\t\tthis.element\n\t\t\t// Cannot directly insertAfter() - we need to detach() first, because\n\t\t\t// insertAfter() will do nothing if the payload div was not attached\n\t\t\t// to the DOM at the time the widget was created, and so the payload\n\t\t\t// will remain inside the container even after we call insertAfter().\n\t\t\t// If that happens and we remove the container a few lines below, we\n\t\t\t// will cause an infinite recursion - #5244\n\t\t\t.detach()\n\t\t\t.insertAfter( this._ui.placeholder )\n\t\t\t.removeClass( \"ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit\" );\n\t\tthis._ui.screen.remove();\n\t\tthis._ui.container.remove();\n\t\tthis._ui.placeholder.remove();\n\t},\n\n\t_destroy: function() {\n\t\tif ( $.mobile.popup.active === this ) {\n\t\t\tthis.element.one( \"popupafterclose\", $.proxy( this, \"_unenhance\" ) );\n\t\t\tthis.close();\n\t\t} else {\n\t\t\tthis._unenhance();\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_closePopup: function( theEvent, data ) {\n\t\tvar parsedDst, toUrl,\n\t\t\tcurrentOptions = this.options,\n\t\t\timmediate = false;\n\n\t\tif ( ( theEvent && theEvent.isDefaultPrevented() ) || $.mobile.popup.active !== this ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// restore location on screen\n\t\twindow.scrollTo( 0, this._scrollTop );\n\n\t\tif ( theEvent && theEvent.type === \"pagebeforechange\" && data ) {\n\t\t\t// Determine whether we need to rapid-close the popup, or whether we can\n\t\t\t// take the time to run the closing transition\n\t\t\tif ( typeof data.toPage === \"string\" ) {\n\t\t\t\tparsedDst = data.toPage;\n\t\t\t} else {\n\t\t\t\tparsedDst = data.toPage.jqmData( \"url\" );\n\t\t\t}\n\t\t\tparsedDst = $.mobile.path.parseUrl( parsedDst );\n\t\t\ttoUrl = parsedDst.pathname + parsedDst.search + parsedDst.hash;\n\n\t\t\tif ( this._myUrl !== $.mobile.path.makeUrlAbsolute( toUrl ) ) {\n\t\t\t\t// Going to a different page - close immediately\n\t\t\t\timmediate = true;\n\t\t\t} else {\n\t\t\t\ttheEvent.preventDefault();\n\t\t\t}\n\t\t}\n\n\t\t// remove nav bindings\n\t\tthis.window.off( currentOptions.closeEvents );\n\t\t// unbind click handlers added when history is disabled\n\t\tthis.element.undelegate( currentOptions.closeLinkSelector, currentOptions.closeLinkEvents );\n\n\t\tthis._close( immediate );\n\t},\n\n\t// any navigation event after a popup is opened should close the popup\n\t// NOTE the pagebeforechange is bound to catch navigation events that don't\n\t//      alter the url (eg, dialogs from popups)\n\t_bindContainerClose: function() {\n\t\tthis.window\n\t\t\t.on( this.options.closeEvents, $.proxy( this, \"_closePopup\" ) );\n\t},\n\n\twidget: function() {\n\t\treturn this._ui.container;\n\t},\n\n\t// TODO no clear deliniation of what should be here and\n\t// what should be in _open. Seems to be \"visual\" vs \"history\" for now\n\topen: function( options ) {\n\t\tvar url, hashkey, activePage, currentIsDialog, hasHash, urlHistory,\n\t\t\tself = this,\n\t\t\tcurrentOptions = this.options;\n\n\t\t// make sure open is idempotent\n\t\tif ( $.mobile.popup.active || currentOptions.disabled ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// set the global popup mutex\n\t\t$.mobile.popup.active = this;\n\t\tthis._scrollTop = this.window.scrollTop();\n\n\t\t// if history alteration is disabled close on navigate events\n\t\t// and leave the url as is\n\t\tif ( !( currentOptions.history ) ) {\n\t\t\tself._open( options );\n\t\t\tself._bindContainerClose();\n\n\t\t\t// When histoy is disabled we have to grab the data-rel\n\t\t\t// back link clicks so we can close the popup instead of\n\t\t\t// relying on history to do it for us\n\t\t\tself.element\n\t\t\t\t.delegate( currentOptions.closeLinkSelector, currentOptions.closeLinkEvents, function( theEvent ) {\n\t\t\t\t\tself.close();\n\t\t\t\t\ttheEvent.preventDefault();\n\t\t\t\t});\n\n\t\t\treturn this;\n\t\t}\n\n\t\t// cache some values for min/readability\n\t\turlHistory = $.mobile.navigate.history;\n\t\thashkey = $.mobile.dialogHashKey;\n\t\tactivePage = $.mobile.activePage;\n\t\tcurrentIsDialog = ( activePage ? activePage.hasClass( \"ui-dialog\" ) : false );\n\t\tthis._myUrl = url = urlHistory.getActive().url;\n\t\thasHash = ( url.indexOf( hashkey ) > -1 ) && !currentIsDialog && ( urlHistory.activeIndex > 0 );\n\n\t\tif ( hasHash ) {\n\t\t\tself._open( options );\n\t\t\tself._bindContainerClose();\n\t\t\treturn this;\n\t\t}\n\n\t\t// if the current url has no dialog hash key proceed as normal\n\t\t// otherwise, if the page is a dialog simply tack on the hash key\n\t\tif ( url.indexOf( hashkey ) === -1 && !currentIsDialog ) {\n\t\t\turl = url + (url.indexOf( \"#\" ) > -1 ? hashkey : \"#\" + hashkey);\n\t\t} else {\n\t\t\turl = $.mobile.path.parseLocation().hash + hashkey;\n\t\t}\n\n\t\t// swallow the the initial navigation event, and bind for the next\n\t\tthis.window.one( \"beforenavigate\", function( theEvent ) {\n\t\t\ttheEvent.preventDefault();\n\t\t\tself._open( options );\n\t\t\tself._bindContainerClose();\n\t\t});\n\n\t\tthis.urlAltered = true;\n\t\t$.mobile.navigate( url, { role: \"dialog\" } );\n\n\t\treturn this;\n\t},\n\n\tclose: function() {\n\t\t// make sure close is idempotent\n\t\tif ( $.mobile.popup.active !== this ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tthis._scrollTop = this.window.scrollTop();\n\n\t\tif ( this.options.history && this.urlAltered ) {\n\t\t\t$.mobile.back();\n\t\t\tthis.urlAltered = false;\n\t\t} else {\n\t\t\t// simulate the nav bindings having fired\n\t\t\tthis._closePopup();\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\n// TODO this can be moved inside the widget\n$.mobile.popup.handleLink = function( $link ) {\n\tvar offset,\n\t\tpath = $.mobile.path,\n\n\t\t// NOTE make sure to get only the hash from the href because ie7 (wp7)\n\t\t//      returns the absolute href in this case ruining the element selection\n\t\tpopup = $( path.hashToSelector( path.parseUrl( $link.attr( \"href\" ) ).hash ) ).first();\n\n\tif ( popup.length > 0 && popup.data( \"mobile-popup\" ) ) {\n\t\toffset = $link.offset();\n\t\tpopup.popup( \"open\", {\n\t\t\tx: offset.left + $link.outerWidth() / 2,\n\t\t\ty: offset.top + $link.outerHeight() / 2,\n\t\t\ttransition: $link.jqmData( \"transition\" ),\n\t\t\tpositionTo: $link.jqmData( \"position-to\" )\n\t\t});\n\t}\n\n\t//remove after delay\n\tsetTimeout( function() {\n\t\t$link.removeClass( $.mobile.activeBtnClass );\n\t}, 300 );\n};\n\n// TODO move inside _create\n$.mobile.document.on( \"pagebeforechange\", function( theEvent, data ) {\n\tif ( data.options.role === \"popup\" ) {\n\t\t$.mobile.popup.handleLink( data.options.link );\n\t\ttheEvent.preventDefault();\n\t}\n});\n\n})( jQuery );\n\n/*\n* custom \"selectmenu\" plugin\n*/\n\n(function( $, undefined ) {\n\nvar unfocusableItemSelector = \".ui-disabled,.ui-state-disabled,.ui-li-divider,.ui-screen-hidden,:jqmData(role='placeholder')\",\n\tgoToAdjacentItem = function( item, target, direction ) {\n\t\tvar adjacent = item[ direction + \"All\" ]()\n\t\t\t.not( unfocusableItemSelector )\n\t\t\t.first();\n\n\t\t// if there's a previous option, focus it\n\t\tif ( adjacent.length ) {\n\t\t\ttarget\n\t\t\t\t.blur()\n\t\t\t\t.attr( \"tabindex\", \"-1\" );\n\n\t\t\tadjacent.find( \"a\" ).first().focus();\n\t\t}\n\t};\n\n$.widget( \"mobile.selectmenu\", $.mobile.selectmenu, {\n\t_create: function() {\n\t\tvar o = this.options;\n\n\t\t// Custom selects cannot exist inside popups, so revert the \"nativeMenu\"\n\t\t// option to true if a parent is a popup\n\t\to.nativeMenu = o.nativeMenu || ( this.element.parents( \":jqmData(role='popup'),:mobile-popup\" ).length > 0 );\n\n\t\treturn this._super();\n\t},\n\n\t_handleSelectFocus: function() {\n\t\tthis.element.blur();\n\t\tthis.button.focus();\n\t},\n\n\t_handleKeydown: function( event ) {\n\t\tthis._super( event );\n\t\tthis._handleButtonVclickKeydown( event );\n\t},\n\n\t_handleButtonVclickKeydown: function( event ) {\n\t\tif ( this.options.disabled || this.isOpen || this.options.nativeMenu ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.type === \"vclick\" ||\n\t\t\t\tevent.keyCode && (event.keyCode === $.mobile.keyCode.ENTER || event.keyCode === $.mobile.keyCode.SPACE)) {\n\n\t\t\tthis._decideFormat();\n\t\t\tif ( this.menuType === \"overlay\" ) {\n\t\t\t\tthis.button.attr( \"href\", \"#\" + this.popupId ).attr( \"data-\" + ( $.mobile.ns || \"\" ) + \"rel\", \"popup\" );\n\t\t\t} else {\n\t\t\t\tthis.button.attr( \"href\", \"#\" + this.dialogId ).attr( \"data-\" + ( $.mobile.ns || \"\" ) + \"rel\", \"dialog\" );\n\t\t\t}\n\t\t\tthis.isOpen = true;\n\t\t\t// Do not prevent default, so the navigation may have a chance to actually open the chosen format\n\t\t}\n\t},\n\n\t_handleListFocus: function( e ) {\n\t\tvar params = ( e.type === \"focusin\" ) ?\n\t\t\t{ tabindex: \"0\", event: \"vmouseover\" }:\n\t\t\t{ tabindex: \"-1\", event: \"vmouseout\" };\n\n\t\t$( e.target )\n\t\t\t.attr( \"tabindex\", params.tabindex )\n\t\t\t.trigger( params.event );\n\t},\n\n\t_handleListKeydown: function( event ) {\n\t\tvar target = $( event.target ),\n\t\t\tli = target.closest( \"li\" );\n\n\t\t// switch logic based on which key was pressed\n\t\tswitch ( event.keyCode ) {\n\t\t\t// up or left arrow keys\n\t\tcase 38:\n\t\t\tgoToAdjacentItem( li, target, \"prev\" );\n\t\t\treturn false;\n\t\t\t// down or right arrow keys\n\t\tcase 40:\n\t\t\tgoToAdjacentItem( li, target, \"next\" );\n\t\t\treturn false;\n\t\t\t// If enter or space is pressed, trigger click\n\t\tcase 13:\n\t\tcase 32:\n\t\t\ttarget.trigger( \"click\" );\n\t\t\treturn false;\n\t\t}\n\t},\n\n\t_handleMenuPageHide: function() {\n\n\t\t// After the dialog's done, we may want to trigger change if the value has actually changed\n\t\tthis._delayedTrigger();\n\n\t\t// TODO centralize page removal binding / handling in the page plugin.\n\t\t// Suggestion from @jblas to do refcounting\n\t\t//\n\t\t// TODO extremely confusing dependency on the open method where the pagehide.remove\n\t\t// bindings are stripped to prevent the parent page from disappearing. The way\n\t\t// we're keeping pages in the DOM right now sucks\n\t\t//\n\t\t// rebind the page remove that was unbound in the open function\n\t\t// to allow for the parent page removal from actions other than the use\n\t\t// of a dialog sized custom select\n\t\t//\n\t\t// doing this here provides for the back button on the custom select dialog\n\t\tthis.thisPage.page( \"bindRemove\" );\n\t},\n\n\t_handleHeaderCloseClick: function() {\n\t\tif ( this.menuType === \"overlay\" ) {\n\t\t\tthis.close();\n\t\t\treturn false;\n\t\t}\n\t},\n\n\t_handleListItemClick: function( event ) {\n\t\tvar listItem = $( event.target ).closest( \"li\" ),\n\n\t\t\t// Index of option tag to be selected\n\t\t\toldIndex = this.select[ 0 ].selectedIndex,\n\t\t\tnewIndex = $.mobile.getAttribute( listItem, \"option-index\" ),\n\t\t\toption = this._selectOptions().eq( newIndex )[ 0 ];\n\n\t\t// Toggle selected status on the tag for multi selects\n\t\toption.selected = this.isMultiple ? !option.selected : true;\n\n\t\t// Toggle checkbox class for multiple selects\n\t\tif ( this.isMultiple ) {\n\t\t\tlistItem.find( \"a\" )\n\t\t\t\t.toggleClass( \"ui-checkbox-on\", option.selected )\n\t\t\t\t.toggleClass( \"ui-checkbox-off\", !option.selected );\n\t\t}\n\n\t\t// If it's not a multiple select, trigger change after it has finished closing\n\t\tif ( !this.isMultiple && oldIndex !== newIndex ) {\n\t\t\tthis._triggerChange = true;\n\t\t}\n\n\t\t// Trigger change if it's a multiple select\n\t\t// Hide custom select for single selects only - otherwise focus clicked item\n\t\t// We need to grab the clicked item the hard way, because the list may have been rebuilt\n\t\tif ( this.isMultiple ) {\n\t\t\tthis.select.trigger( \"change\" );\n\t\t\tthis.list.find( \"li:not(.ui-li-divider)\" ).eq( newIndex )\n\t\t\t\t.find( \"a\" ).first().focus();\n\t\t}\n\t\telse {\n\t\t\tthis.close();\n\t\t}\n\n\t\tevent.preventDefault();\n\t},\n\n\tbuild: function() {\n\t\tvar selectId, popupId, dialogId, label, thisPage, isMultiple, menuId,\n\t\t\tthemeAttr, overlayTheme, overlayThemeAttr, dividerThemeAttr,\n\t\t\tmenuPage, listbox, list, header, headerTitle, menuPageContent,\n\t\t\tmenuPageClose, headerClose,\n\t\t\to = this.options;\n\n\t\tif ( o.nativeMenu ) {\n\t\t\treturn this._super();\n\t\t}\n\n\t\tselectId = this.selectId;\n\t\tpopupId = selectId + \"-listbox\";\n\t\tdialogId = selectId + \"-dialog\";\n\t\tlabel = this.label;\n\t\tthisPage = this.element.closest( \".ui-page\" );\n\t\tisMultiple = this.element[ 0 ].multiple;\n\t\tmenuId = selectId + \"-menu\";\n\t\tthemeAttr = o.theme ? ( \" data-\" + $.mobile.ns + \"theme='\" + o.theme + \"'\" ) : \"\";\n\t\toverlayTheme = o.overlayTheme || o.theme || null;\n\t\toverlayThemeAttr = overlayTheme ? ( \" data-\" + $.mobile.ns +\n\t\t\t\"overlay-theme='\" + overlayTheme + \"'\" ) : \"\";\n\t\tdividerThemeAttr = ( o.dividerTheme && isMultiple ) ? ( \" data-\" + $.mobile.ns + \"divider-theme='\" + o.dividerTheme + \"'\" ) : \"\";\n\t\tmenuPage = $( \"<div data-\" + $.mobile.ns + \"role='dialog' class='ui-selectmenu' id='\" + dialogId + \"'\" + themeAttr + overlayThemeAttr + \">\" +\n\t\t\t\"<div data-\" + $.mobile.ns + \"role='header'>\" +\n\t\t\t\"<div class='ui-title'></div>\"+\n\t\t\t\"</div>\"+\n\t\t\t\"<div data-\" + $.mobile.ns + \"role='content'></div>\"+\n\t\t\t\"</div>\" );\n\t\tlistbox = $( \"<div\" + themeAttr + overlayThemeAttr + \" id='\" + popupId +\n\t\t\t\t\"' class='ui-selectmenu'></div>\" )\n\t\t\t.insertAfter( this.select )\n\t\t\t.popup();\n\t\tlist = $( \"<ul class='ui-selectmenu-list' id='\" + menuId + \"' role='listbox' aria-labelledby='\" + this.buttonId + \"'\" + themeAttr + dividerThemeAttr + \"></ul>\" ).appendTo( listbox );\n\t\theader = $( \"<div class='ui-header ui-bar-\" + ( o.theme ? o.theme : \"inherit\" ) + \"'></div>\" ).prependTo( listbox );\n\t\theaderTitle = $( \"<h1 class='ui-title'></h1>\" ).appendTo( header );\n\n\t\tif ( this.isMultiple ) {\n\t\t\theaderClose = $( \"<a>\", {\n\t\t\t\t\"role\": \"button\",\n\t\t\t\t\"text\": o.closeText,\n\t\t\t\t\"href\": \"#\",\n\t\t\t\t\"class\": \"ui-btn ui-corner-all ui-btn-left ui-btn-icon-notext ui-icon-delete\"\n\t\t\t}).appendTo( header );\n\t\t}\n\n\t\t$.extend( this, {\n\t\t\tselectId: selectId,\n\t\t\tmenuId: menuId,\n\t\t\tpopupId: popupId,\n\t\t\tdialogId: dialogId,\n\t\t\tthisPage: thisPage,\n\t\t\tmenuPage: menuPage,\n\t\t\tlabel: label,\n\t\t\tisMultiple: isMultiple,\n\t\t\ttheme: o.theme,\n\t\t\tlistbox: listbox,\n\t\t\tlist: list,\n\t\t\theader: header,\n\t\t\theaderTitle: headerTitle,\n\t\t\theaderClose: headerClose,\n\t\t\tmenuPageContent: menuPageContent,\n\t\t\tmenuPageClose: menuPageClose,\n\t\t\tplaceholder: \"\"\n\t\t});\n\n\t\t// Create list from select, update state\n\t\tthis.refresh();\n\n\t\tif ( this._origTabIndex === undefined ) {\n\t\t\t// Map undefined to false, because this._origTabIndex === undefined\n\t\t\t// indicates that we have not yet checked whether the select has\n\t\t\t// originally had a tabindex attribute, whereas false indicates that\n\t\t\t// we have checked the select for such an attribute, and have found\n\t\t\t// none present.\n\t\t\tthis._origTabIndex = ( this.select[ 0 ].getAttribute( \"tabindex\" ) === null ) ? false : this.select.attr( \"tabindex\" );\n\t\t}\n\t\tthis.select.attr( \"tabindex\", \"-1\" );\n\t\tthis._on( this.select, { focus : \"_handleSelectFocus\" } );\n\n\t\t// Button events\n\t\tthis._on( this.button, {\n\t\t\tvclick: \"_handleButtonVclickKeydown\"\n\t\t});\n\n\t\t// Events for list items\n\t\tthis.list.attr( \"role\", \"listbox\" );\n\t\tthis._on( this.list, {\n\t\t\t\"focusin\": \"_handleListFocus\",\n\t\t\t\"focusout\": \"_handleListFocus\",\n\t\t\t\"keydown\": \"_handleListKeydown\",\n\t\t\t\"click li:not(.ui-disabled,.ui-state-disabled,.ui-li-divider)\": \"_handleListItemClick\"\n\t\t});\n\n\t\t// button refocus ensures proper height calculation\n\t\t// by removing the inline style and ensuring page inclusion\n\t\tthis._on( this.menuPage, { pagehide: \"_handleMenuPageHide\" } );\n\n\t\t// Events on the popup\n\t\tthis._on( this.listbox, { popupafterclose: \"_popupClosed\" } );\n\n\t\t// Close button on small overlays\n\t\tif ( this.isMultiple ) {\n\t\t\tthis._on( this.headerClose, { click: \"_handleHeaderCloseClick\" } );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_popupClosed: function() {\n\t\tthis.close();\n\t\tthis._delayedTrigger();\n\t},\n\n\t_delayedTrigger: function() {\n\t\tif ( this._triggerChange ) {\n\t\t\tthis.element.trigger( \"change\" );\n\t\t}\n\t\tthis._triggerChange = false;\n\t},\n\n\t_isRebuildRequired: function() {\n\t\tvar list = this.list.find( \"li\" ),\n\t\t\toptions = this._selectOptions().not( \".ui-screen-hidden\" );\n\n\t\t// TODO exceedingly naive method to determine difference\n\t\t// ignores value changes etc in favor of a forcedRebuild\n\t\t// from the user in the refresh method\n\t\treturn options.text() !== list.text();\n\t},\n\n\tselected: function() {\n\t\treturn this._selectOptions().filter( \":selected:not( :jqmData(placeholder='true') )\" );\n\t},\n\n\trefresh: function( force ) {\n\t\tvar self, indices;\n\n\t\tif ( this.options.nativeMenu ) {\n\t\t\treturn this._super( force );\n\t\t}\n\n\t\tself = this;\n\t\tif ( force || this._isRebuildRequired() ) {\n\t\t\tself._buildList();\n\t\t}\n\n\t\tindices = this.selectedIndices();\n\n\t\tself.setButtonText();\n\t\tself.setButtonCount();\n\n\t\tself.list.find( \"li:not(.ui-li-divider)\" )\n\t\t\t.find( \"a\" ).removeClass( $.mobile.activeBtnClass ).end()\n\t\t\t.attr( \"aria-selected\", false )\n\t\t\t.each(function( i ) {\n\t\t\t\tvar item = $( this );\n\t\t\t\tif ( $.inArray( i, indices ) > -1 ) {\n\n\t\t\t\t\t// Aria selected attr\n\t\t\t\t\titem.attr( \"aria-selected\", true );\n\n\t\t\t\t\t// Multiple selects: add the \"on\" checkbox state to the icon\n\t\t\t\t\tif ( self.isMultiple ) {\n\t\t\t\t\t\titem.find( \"a\" ).removeClass( \"ui-checkbox-off\" ).addClass( \"ui-checkbox-on\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( item.hasClass( \"ui-screen-hidden\" ) ) {\n\t\t\t\t\t\t\titem.next().find( \"a\" ).addClass( $.mobile.activeBtnClass );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titem.find( \"a\" ).addClass( $.mobile.activeBtnClass );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ( self.isMultiple ) {\n\t\t\t\t\titem.find( \"a\" ).removeClass( \"ui-checkbox-on\" ).addClass( \"ui-checkbox-off\" );\n\t\t\t\t}\n\t\t\t});\n\t},\n\n\tclose: function() {\n\t\tif ( this.options.disabled || !this.isOpen ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar self = this;\n\n\t\tif ( self.menuType === \"page\" ) {\n\t\t\tself.menuPage.dialog( \"close\" );\n\t\t\tself.list.appendTo( self.listbox );\n\t\t} else {\n\t\t\tself.listbox.popup( \"close\" );\n\t\t}\n\n\t\tself._focusButton();\n\t\t// allow the dialog to be closed again\n\t\tself.isOpen = false;\n\t},\n\n\topen: function() {\n\t\tthis.button.click();\n\t},\n\n\t_focusMenuItem: function() {\n\t\tvar selector = this.list.find( \"a.\" + $.mobile.activeBtnClass );\n\t\tif ( selector.length === 0 ) {\n\t\t\tselector = this.list.find( \"li:not(\" + unfocusableItemSelector + \") a.ui-btn\" );\n\t\t}\n\t\tselector.first().focus();\n\t},\n\n\t_decideFormat: function() {\n\t\tvar self = this,\n\t\t\t$window = this.window,\n\t\t\tselfListParent = self.list.parent(),\n\t\t\tmenuHeight = selfListParent.outerHeight(),\n\t\t\tscrollTop = $window.scrollTop(),\n\t\t\tbtnOffset = self.button.offset().top,\n\t\t\tscreenHeight = $window.height();\n\n\t\tif ( menuHeight > screenHeight - 80 || !$.support.scrollTop ) {\n\n\t\t\tself.menuPage.appendTo( $.mobile.pageContainer ).page();\n\t\t\tself.menuPageContent = self.menuPage.find( \".ui-content\" );\n\t\t\tself.menuPageClose = self.menuPage.find( \".ui-header a\" );\n\n\t\t\t// prevent the parent page from being removed from the DOM,\n\t\t\t// otherwise the results of selecting a list item in the dialog\n\t\t\t// fall into a black hole\n\t\t\tself.thisPage.unbind( \"pagehide.remove\" );\n\n\t\t\t//for WebOS/Opera Mini (set lastscroll using button offset)\n\t\t\tif ( scrollTop === 0 && btnOffset > screenHeight ) {\n\t\t\t\tself.thisPage.one( \"pagehide\", function() {\n\t\t\t\t\t$( this ).jqmData( \"lastScroll\", btnOffset );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tself.menuPage.one( {\n\t\t\t\tpageshow: $.proxy( this, \"_focusMenuItem\" ),\n\t\t\t\tpagehide: $.proxy( this, \"close\" )\n\t\t\t});\n\n\t\t\tself.menuType = \"page\";\n\t\t\tself.menuPageContent.append( self.list );\n\t\t\tself.menuPage\n\t\t\t\t.find( \"div .ui-title\" )\n\t\t\t\t\t.text( self.label.getEncodedText() || self.placeholder );\n\t\t} else {\n\t\t\tself.menuType = \"overlay\";\n\n\t\t\tself.listbox.one( { popupafteropen: $.proxy( this, \"_focusMenuItem\" ) } );\n\t\t}\n\t},\n\n\t_buildList: function() {\n\t\tvar self = this,\n\t\t\to = this.options,\n\t\t\tplaceholder = this.placeholder,\n\t\t\tneedPlaceholder = true,\n\t\t\tdataIcon = \"false\",\n\t\t\t$options, numOptions, select,\n\t\t\tdataPrefix = \"data-\" + $.mobile.ns,\n\t\t\tdataIndexAttr = dataPrefix + \"option-index\",\n\t\t\tdataIconAttr = dataPrefix + \"icon\",\n\t\t\tdataRoleAttr = dataPrefix + \"role\",\n\t\t\tdataPlaceholderAttr = dataPrefix + \"placeholder\",\n\t\t\tfragment = document.createDocumentFragment(),\n\t\t\tisPlaceholderItem = false,\n\t\t\toptGroup,\n\t\t\ti,\n\t\t\toption, $option, parent, text, anchor, classes,\n\t\t\toptLabel, divider, item;\n\n\t\tself.list.empty().filter( \".ui-listview\" ).listview( \"destroy\" );\n\t\t$options = this._selectOptions();\n\t\tnumOptions = $options.length;\n\t\tselect = this.select[ 0 ];\n\n\t\tfor ( i = 0; i < numOptions;i++, isPlaceholderItem = false) {\n\t\t\toption = $options[i];\n\t\t\t$option = $( option );\n\n\t\t\t// Do not create options based on ui-screen-hidden select options\n\t\t\tif ( $option.hasClass( \"ui-screen-hidden\" ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tparent = option.parentNode;\n\t\t\tclasses = [];\n\n\t\t\t// Although using .text() here raises the risk that, when we later paste this into the\n\t\t\t// list item we end up pasting possibly malicious things like <script> tags, that risk\n\t\t\t// only arises if we do something like $( \"<li><a href='#'>\" + text + \"</a></li>\" ). We\n\t\t\t// don't do that. We do document.createTextNode( text ) instead, which guarantees that\n\t\t\t// whatever we paste in will end up as text, with characters like <, > and & escaped.\n\t\t\ttext = $option.text();\n\t\t\tanchor = document.createElement( \"a\" );\n\t\t\tanchor.setAttribute( \"href\", \"#\" );\n\t\t\tanchor.appendChild( document.createTextNode( text ) );\n\n\t\t\t// Are we inside an optgroup?\n\t\t\tif ( parent !== select && parent.nodeName.toLowerCase() === \"optgroup\" ) {\n\t\t\t\toptLabel = parent.getAttribute( \"label\" );\n\t\t\t\tif ( optLabel !== optGroup ) {\n\t\t\t\t\tdivider = document.createElement( \"li\" );\n\t\t\t\t\tdivider.setAttribute( dataRoleAttr, \"list-divider\" );\n\t\t\t\t\tdivider.setAttribute( \"role\", \"option\" );\n\t\t\t\t\tdivider.setAttribute( \"tabindex\", \"-1\" );\n\t\t\t\t\tdivider.appendChild( document.createTextNode( optLabel ) );\n\t\t\t\t\tfragment.appendChild( divider );\n\t\t\t\t\toptGroup = optLabel;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( needPlaceholder && ( !option.getAttribute( \"value\" ) || text.length === 0 || $option.jqmData( \"placeholder\" ) ) ) {\n\t\t\t\tneedPlaceholder = false;\n\t\t\t\tisPlaceholderItem = true;\n\n\t\t\t\t// If we have identified a placeholder, record the fact that it was\n\t\t\t\t// us who have added the placeholder to the option and mark it\n\t\t\t\t// retroactively in the select as well\n\t\t\t\tif ( null === option.getAttribute( dataPlaceholderAttr ) ) {\n\t\t\t\t\tthis._removePlaceholderAttr = true;\n\t\t\t\t}\n\t\t\t\toption.setAttribute( dataPlaceholderAttr, true );\n\t\t\t\tif ( o.hidePlaceholderMenuItems ) {\n\t\t\t\t\tclasses.push( \"ui-screen-hidden\" );\n\t\t\t\t}\n\t\t\t\tif ( placeholder !== text ) {\n\t\t\t\t\tplaceholder = self.placeholder = text;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\titem = document.createElement( \"li\" );\n\t\t\tif ( option.disabled ) {\n\t\t\t\tclasses.push( \"ui-state-disabled\" );\n\t\t\t\titem.setAttribute( \"aria-disabled\", true );\n\t\t\t}\n\t\t\titem.setAttribute( dataIndexAttr, i );\n\t\t\titem.setAttribute( dataIconAttr, dataIcon );\n\t\t\tif ( isPlaceholderItem ) {\n\t\t\t\titem.setAttribute( dataPlaceholderAttr, true );\n\t\t\t}\n\t\t\titem.className = classes.join( \" \" );\n\t\t\titem.setAttribute( \"role\", \"option\" );\n\t\t\tanchor.setAttribute( \"tabindex\", \"-1\" );\n\t\t\tif ( this.isMultiple ) {\n\t\t\t\t$( anchor ).addClass( \"ui-btn ui-checkbox-off ui-btn-icon-right\" );\n\t\t\t}\n\n\t\t\titem.appendChild( anchor );\n\t\t\tfragment.appendChild( item );\n\t\t}\n\n\t\tself.list[0].appendChild( fragment );\n\n\t\t// Hide header if it's not a multiselect and there's no placeholder\n\t\tif ( !this.isMultiple && !placeholder.length ) {\n\t\t\tthis.header.addClass( \"ui-screen-hidden\" );\n\t\t} else {\n\t\t\tthis.headerTitle.text( this.placeholder );\n\t\t}\n\n\t\t// Now populated, create listview\n\t\tself.list.listview();\n\t},\n\n\t_button: function() {\n\t\treturn this.options.nativeMenu ?\n\t\t\tthis._super() :\n\t\t\t$( \"<a>\", {\n\t\t\t\t\"href\": \"#\",\n\t\t\t\t\"role\": \"button\",\n\t\t\t\t// TODO value is undefined at creation\n\t\t\t\t\"id\": this.buttonId,\n\t\t\t\t\"aria-haspopup\": \"true\",\n\n\t\t\t\t// TODO value is undefined at creation\n\t\t\t\t\"aria-owns\": this.menuId\n\t\t\t});\n\t},\n\n\t_destroy: function() {\n\n\t\tif ( !this.options.nativeMenu ) {\n\t\t\tthis.close();\n\n\t\t\t// Restore the tabindex attribute to its original value\n\t\t\tif ( this._origTabIndex !== undefined ) {\n\t\t\t\tif ( this._origTabIndex !== false ) {\n\t\t\t\t\tthis.select.attr( \"tabindex\", this._origTabIndex );\n\t\t\t\t} else {\n\t\t\t\t\tthis.select.removeAttr( \"tabindex\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove the placeholder attribute if we were the ones to add it\n\t\t\tif ( this._removePlaceholderAttr ) {\n\t\t\t\tthis._selectOptions().removeAttr( \"data-\" + $.mobile.ns + \"placeholder\" );\n\t\t\t}\n\n\t\t\t// Remove the popup\n\t\t\tthis.listbox.remove();\n\n\t\t\t// Remove the dialog\n\t\t\tthis.menuPage.remove();\n\t\t}\n\n\t\t// Chain up\n\t\tthis._super();\n\t}\n});\n\n})( jQuery );\n\n\n// buttonMarkup is deprecated as of 1.4.0 and will be removed in 1.5.0.\n\n(function( $, undefined ) {\n\n// General policy: Do not access data-* attributes except during enhancement.\n// In all other cases we determine the state of the button exclusively from its\n// className. That's why optionsToClasses expects a full complement of options,\n// and the jQuery plugin completes the set of options from the default values.\n\n// Map classes to buttonMarkup boolean options - used in classNameToOptions()\nvar reverseBoolOptionMap = {\n\t\t\"ui-shadow\" : \"shadow\",\n\t\t\"ui-corner-all\" : \"corners\",\n\t\t\"ui-btn-inline\" : \"inline\",\n\t\t\"ui-shadow-icon\" : \"iconshadow\", /* TODO: Remove in 1.5 */\n\t\t\"ui-mini\" : \"mini\"\n\t},\n\tgetAttrFixed = function() {\n\t\tvar ret = $.mobile.getAttribute.apply( this, arguments );\n\n\t\treturn ( ret == null ? undefined : ret );\n\t},\n\tcapitalLettersRE = /[A-Z]/g;\n\n// optionsToClasses:\n// @options: A complete set of options to convert to class names.\n// @existingClasses: extra classes to add to the result\n//\n// Converts @options to buttonMarkup classes and returns the result as an array\n// that can be converted to an element's className with .join( \" \" ). All\n// possible options must be set inside @options. Use $.fn.buttonMarkup.defaults\n// to get a complete set and use $.extend to override your choice of options\n// from that set.\nfunction optionsToClasses( options, existingClasses ) {\n\tvar classes = existingClasses ? existingClasses : [];\n\n\t// Add classes to the array - first ui-btn\n\tclasses.push( \"ui-btn\" );\n\n\t// If there is a theme\n\tif ( options.theme ) {\n\t\tclasses.push( \"ui-btn-\" + options.theme );\n\t}\n\n\t// If there's an icon, add the icon-related classes\n\tif ( options.icon ) {\n\t\tclasses = classes.concat([\n\t\t\t\"ui-icon-\" + options.icon,\n\t\t\t\"ui-btn-icon-\" + options.iconpos\n\t\t]);\n\t\tif ( options.iconshadow ) {\n\t\t\tclasses.push( \"ui-shadow-icon\" ); /* TODO: Remove in 1.5 */\n\t\t}\n\t}\n\n\t// Add the appropriate class for each boolean option\n\tif ( options.inline ) {\n\t\tclasses.push( \"ui-btn-inline\" );\n\t}\n\tif ( options.shadow ) {\n\t\tclasses.push( \"ui-shadow\" );\n\t}\n\tif ( options.corners ) {\n\t\tclasses.push( \"ui-corner-all\" );\n\t}\n\tif ( options.mini ) {\n\t\tclasses.push( \"ui-mini\" );\n\t}\n\n\t// Create a string from the array and return it\n\treturn classes;\n}\n\n// classNameToOptions:\n// @classes: A string containing a .className-style space-separated class list\n//\n// Loops over @classes and calculates an options object based on the\n// buttonMarkup-related classes it finds. It records unrecognized classes in an\n// array.\n//\n// Returns: An object containing the following items:\n//\n// \"options\": buttonMarkup options found to be present because of the\n// presence/absence of corresponding classes\n//\n// \"unknownClasses\": a string containing all the non-buttonMarkup-related\n// classes found in @classes\n//\n// \"alreadyEnhanced\": A boolean indicating whether the ui-btn class was among\n// those found to be present\nfunction classNameToOptions( classes ) {\n\tvar idx, map, unknownClass,\n\t\talreadyEnhanced = false,\n\t\tnoIcon = true,\n\t\to = {\n\t\t\ticon: \"\",\n\t\t\tinline: false,\n\t\t\tshadow: false,\n\t\t\tcorners: false,\n\t\t\ticonshadow: false,\n\t\t\tmini: false\n\t\t},\n\t\tunknownClasses = [];\n\n\tclasses = classes.split( \" \" );\n\n\t// Loop over the classes\n\tfor ( idx = 0 ; idx < classes.length ; idx++ ) {\n\n\t\t// Assume it's an unrecognized class\n\t\tunknownClass = true;\n\n\t\t// Recognize boolean options from the presence of classes\n\t\tmap = reverseBoolOptionMap[ classes[ idx ] ];\n\t\tif ( map !== undefined ) {\n\t\t\tunknownClass = false;\n\t\t\to[ map ] = true;\n\n\t\t// Recognize the presence of an icon and establish the icon position\n\t\t} else if ( classes[ idx ].indexOf( \"ui-btn-icon-\" ) === 0 ) {\n\t\t\tunknownClass = false;\n\t\t\tnoIcon = false;\n\t\t\to.iconpos = classes[ idx ].substring( 12 );\n\n\t\t// Establish which icon is present\n\t\t} else if ( classes[ idx ].indexOf( \"ui-icon-\" ) === 0 ) {\n\t\t\tunknownClass = false;\n\t\t\to.icon = classes[ idx ].substring( 8 );\n\n\t\t// Establish the theme - this recognizes one-letter theme swatch names\n\t\t} else if ( classes[ idx ].indexOf( \"ui-btn-\" ) === 0 && classes[ idx ].length === 8 ) {\n\t\t\tunknownClass = false;\n\t\t\to.theme = classes[ idx ].substring( 7 );\n\n\t\t// Recognize that this element has already been buttonMarkup-enhanced\n\t\t} else if ( classes[ idx ] === \"ui-btn\" ) {\n\t\t\tunknownClass = false;\n\t\t\talreadyEnhanced = true;\n\t\t}\n\n\t\t// If this class has not been recognized, add it to the list\n\t\tif ( unknownClass ) {\n\t\t\tunknownClasses.push( classes[ idx ] );\n\t\t}\n\t}\n\n\t// If a \"ui-btn-icon-*\" icon position class is absent there cannot be an icon\n\tif ( noIcon ) {\n\t\to.icon = \"\";\n\t}\n\n\treturn {\n\t\toptions: o,\n\t\tunknownClasses: unknownClasses,\n\t\talreadyEnhanced: alreadyEnhanced\n\t};\n}\n\nfunction camelCase2Hyphenated( c ) {\n\treturn \"-\" + c.toLowerCase();\n}\n\n// $.fn.buttonMarkup:\n// DOM: gets/sets .className\n//\n// @options: options to apply to the elements in the jQuery object\n// @overwriteClasses: boolean indicating whether to honour existing classes\n//\n// Calculates the classes to apply to the elements in the jQuery object based on\n// the options passed in. If @overwriteClasses is true, it sets the className\n// property of each element in the jQuery object to the buttonMarkup classes\n// it calculates based on the options passed in.\n//\n// If you wish to preserve any classes that are already present on the elements\n// inside the jQuery object, including buttonMarkup-related classes that were\n// added by a previous call to $.fn.buttonMarkup() or during page enhancement\n// then you should omit @overwriteClasses or set it to false.\n$.fn.buttonMarkup = function( options, overwriteClasses ) {\n\tvar idx, data, el, retrievedOptions, optionKey,\n\t\tdefaults = $.fn.buttonMarkup.defaults;\n\n\tfor ( idx = 0 ; idx < this.length ; idx++ ) {\n\t\tel = this[ idx ];\n\t\tdata = overwriteClasses ?\n\n\t\t\t// Assume this element is not enhanced and ignore its classes\n\t\t\t{ alreadyEnhanced: false, unknownClasses: [] } :\n\n\t\t\t// Otherwise analyze existing classes to establish existing options and\n\t\t\t// classes\n\t\t\tclassNameToOptions( el.className );\n\n\t\tretrievedOptions = $.extend( {},\n\n\t\t\t// If the element already has the class ui-btn, then we assume that\n\t\t\t// it has passed through buttonMarkup before - otherwise, the options\n\t\t\t// returned by classNameToOptions do not correctly reflect the state of\n\t\t\t// the element\n\t\t\t( data.alreadyEnhanced ? data.options : {} ),\n\n\t\t\t// Finally, apply the options passed in\n\t\t\toptions );\n\n\t\t// If this is the first call on this element, retrieve remaining options\n\t\t// from the data-attributes\n\t\tif ( !data.alreadyEnhanced ) {\n\t\t\tfor ( optionKey in defaults ) {\n\t\t\t\tif ( retrievedOptions[ optionKey ] === undefined ) {\n\t\t\t\t\tretrievedOptions[ optionKey ] = getAttrFixed( el,\n\t\t\t\t\t\toptionKey.replace( capitalLettersRE, camelCase2Hyphenated )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tel.className = optionsToClasses(\n\n\t\t\t// Merge all the options and apply them as classes\n\t\t\t$.extend( {},\n\n\t\t\t\t// The defaults form the basis\n\t\t\t\tdefaults,\n\n\t\t\t\t// Add the computed options\n\t\t\t\tretrievedOptions\n\t\t\t),\n\n\t\t\t// ... and re-apply any unrecognized classes that were found\n\t\t\tdata.unknownClasses ).join( \" \" );\n\t\tif ( el.tagName.toLowerCase() !== \"button\" ) {\n\t\t\tel.setAttribute( \"role\", \"button\" );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n// buttonMarkup defaults. This must be a complete set, i.e., a value must be\n// given here for all recognized options\n$.fn.buttonMarkup.defaults = {\n\ticon: \"\",\n\ticonpos: \"left\",\n\ttheme: null,\n\tinline: false,\n\tshadow: true,\n\tcorners: true,\n\ticonshadow: false, /* TODO: Remove in 1.5. Option deprecated in 1.4. */\n\tmini: false\n};\n\n$.extend( $.fn.buttonMarkup, {\n\tinitSelector: \"a:jqmData(role='button'), .ui-bar > a, .ui-bar > :jqmData(role='controlgroup') > a, button:not(:jqmData(role='navbar') button)\"\n});\n\n})( jQuery );\n\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.controlgroup\", $.extend( {\n\toptions: {\n\t\tenhanced: false,\n\t\ttheme: null,\n\t\tshadow: false,\n\t\tcorners: true,\n\t\texcludeInvisible: true,\n\t\ttype: \"vertical\",\n\t\tmini: false\n\t},\n\n\t_create: function() {\n\t\tvar elem = this.element,\n\t\t\topts = this.options,\n\t\t\tkeepNative = $.mobile.page.prototype.keepNativeSelector();\n\n\t\t// Run buttonmarkup\n\t\tif ( $.fn.buttonMarkup ) {\n\t\t\tthis.element\n\t\t\t\t.find( $.fn.buttonMarkup.initSelector )\n\t\t\t\t.not( keepNative )\n\t\t\t\t.buttonMarkup();\n\t\t}\n\t\t// Enhance child widgets\n\t\t$.each( this._childWidgets, $.proxy( function( number, widgetName ) {\n\t\t\tif ( $.mobile[ widgetName ] ) {\n\t\t\t\tthis.element\n\t\t\t\t\t.find( $.mobile[ widgetName ].initSelector )\n\t\t\t\t\t.not( keepNative )[ widgetName ]();\n\t\t\t}\n\t\t}, this ));\n\n\t\t$.extend( this, {\n\t\t\t_ui: null,\n\t\t\t_initialRefresh: true\n\t\t});\n\n\t\tif ( opts.enhanced ) {\n\t\t\tthis._ui = {\n\t\t\t\tgroupLegend: elem.children( \".ui-controlgroup-label\" ).children(),\n\t\t\t\tchildWrapper: elem.children( \".ui-controlgroup-controls\" )\n\t\t\t};\n\t\t} else {\n\t\t\tthis._ui = this._enhance();\n\t\t}\n\n\t},\n\n\t_childWidgets: [ \"checkboxradio\", \"selectmenu\", \"button\" ],\n\n\t_themeClassFromOption: function( value ) {\n\t\treturn ( value ? ( value === \"none\" ? \"\" : \"ui-group-theme-\" + value ) : \"\" );\n\t},\n\n\t_enhance: function() {\n\t\tvar elem = this.element,\n\t\t\topts = this.options,\n\t\t\tui = {\n\t\t\t\tgroupLegend: elem.children( \"legend\" ),\n\t\t\t\tchildWrapper: elem\n\t\t\t\t\t.addClass( \"ui-controlgroup \" +\n\t\t\t\t\t\t\"ui-controlgroup-\" +\n\t\t\t\t\t\t\t( opts.type === \"horizontal\" ? \"horizontal\" : \"vertical\" ) + \" \" +\n\t\t\t\t\t\tthis._themeClassFromOption( opts.theme ) + \" \" +\n\t\t\t\t\t\t( opts.corners ? \"ui-corner-all \" : \"\" ) +\n\t\t\t\t\t\t( opts.mini ? \"ui-mini \" : \"\" ) )\n\t\t\t\t\t.wrapInner( \"<div \" +\n\t\t\t\t\t\t\"class='ui-controlgroup-controls \" +\n\t\t\t\t\t\t\t( opts.shadow === true ? \"ui-shadow\" : \"\" ) + \"'></div>\" )\n\t\t\t\t\t.children()\n\t\t\t};\n\n\t\tif ( ui.groupLegend.length > 0 ) {\n\t\t\t$( \"<div role='heading' class='ui-controlgroup-label'></div>\" )\n\t\t\t\t.append( ui.groupLegend )\n\t\t\t\t.prependTo( elem );\n\t\t}\n\n\t\treturn ui;\n\t},\n\n\t_init: function() {\n\t\tthis.refresh();\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar callRefresh, returnValue,\n\t\t\telem = this.element;\n\n\t\t// Must have one of horizontal or vertical\n\t\tif ( options.type !== undefined ) {\n\t\t\telem\n\t\t\t\t.removeClass( \"ui-controlgroup-horizontal ui-controlgroup-vertical\" )\n\t\t\t\t.addClass( \"ui-controlgroup-\" + ( options.type === \"horizontal\" ? \"horizontal\" : \"vertical\" ) );\n\t\t\tcallRefresh = true;\n\t\t}\n\n\t\tif ( options.theme !== undefined ) {\n\t\t\telem\n\t\t\t\t.removeClass( this._themeClassFromOption( this.options.theme ) )\n\t\t\t\t.addClass( this._themeClassFromOption( options.theme ) );\n\t\t}\n\n\t\tif ( options.corners !== undefined ) {\n\t\t\telem.toggleClass( \"ui-corner-all\", options.corners );\n\t\t}\n\n\t\tif ( options.mini !== undefined ) {\n\t\t\telem.toggleClass( \"ui-mini\", options.mini );\n\t\t}\n\n\t\tif ( options.shadow !== undefined ) {\n\t\t\tthis._ui.childWrapper.toggleClass( \"ui-shadow\", options.shadow );\n\t\t}\n\n\t\tif ( options.excludeInvisible !== undefined ) {\n\t\t\tthis.options.excludeInvisible = options.excludeInvisible;\n\t\t\tcallRefresh = true;\n\t\t}\n\n\t\treturnValue = this._super( options );\n\n\t\tif ( callRefresh ) {\n\t\t\tthis.refresh();\n\t\t}\n\n\t\treturn returnValue;\n\t},\n\n\tcontainer: function() {\n\t\treturn this._ui.childWrapper;\n\t},\n\n\trefresh: function() {\n\t\tvar $el = this.container(),\n\t\t\tels = $el.find( \".ui-btn\" ).not( \".ui-slider-handle\" ),\n\t\t\tcreate = this._initialRefresh;\n\t\tif ( $.mobile.checkboxradio ) {\n\t\t\t$el.find( \":mobile-checkboxradio\" ).checkboxradio( \"refresh\" );\n\t\t}\n\t\tthis._addFirstLastClasses( els,\n\t\t\tthis.options.excludeInvisible ? this._getVisibles( els, create ) : els,\n\t\t\tcreate );\n\t\tthis._initialRefresh = false;\n\t},\n\n\t// Caveat: If the legend is not the first child of the controlgroup at enhance\n\t// time, it will be after _destroy().\n\t_destroy: function() {\n\t\tvar ui, buttons,\n\t\t\topts = this.options;\n\n\t\tif ( opts.enhanced ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tui = this._ui;\n\t\tbuttons = this.element\n\t\t\t.removeClass( \"ui-controlgroup \" +\n\t\t\t\t\"ui-controlgroup-horizontal ui-controlgroup-vertical ui-corner-all ui-mini \" +\n\t\t\t\tthis._themeClassFromOption( opts.theme ) )\n\t\t\t.find( \".ui-btn\" )\n\t\t\t.not( \".ui-slider-handle\" );\n\n\t\tthis._removeFirstLastClasses( buttons );\n\n\t\tui.groupLegend.unwrap();\n\t\tui.childWrapper.children().unwrap();\n\t}\n}, $.mobile.behaviors.addFirstLastClasses ) );\n\n})(jQuery);\n\n(function( $, undefined ) {\n\n\t$.widget( \"mobile.toolbar\", {\n\t\tinitSelector: \":jqmData(role='footer'), :jqmData(role='header')\",\n\n\t\toptions: {\n\t\t\ttheme: null,\n\t\t\taddBackBtn: false,\n\t\t\tbackBtnTheme: null,\n\t\t\tbackBtnText: \"Back\"\n\t\t},\n\n\t\t_create: function() {\n\t\t\tvar leftbtn, rightbtn,\n\t\t\t\trole =  this.element.is( \":jqmData(role='header')\" ) ? \"header\" : \"footer\",\n\t\t\t\tpage = this.element.closest( \".ui-page\" );\n\t\t\tif ( page.length === 0 ) {\n\t\t\t\tpage = false;\n\t\t\t\tthis._on( this.document, {\n\t\t\t\t\t\"pageshow\": \"refresh\"\n\t\t\t\t});\n\t\t\t}\n\t\t\t$.extend( this, {\n\t\t\t\trole: role,\n\t\t\t\tpage: page,\n\t\t\t\tleftbtn: leftbtn,\n\t\t\t\trightbtn: rightbtn\n\t\t\t});\n\t\t\tthis.element.attr( \"role\", role === \"header\" ? \"banner\" : \"contentinfo\" ).addClass( \"ui-\" + role );\n\t\t\tthis.refresh();\n\t\t\tthis._setOptions( this.options );\n\t\t},\n\t\t_setOptions: function( o ) {\n\t\t\tif ( o.addBackBtn !== undefined ) {\n\t\t\t\tthis._updateBackButton();\n\t\t\t}\n\t\t\tif ( o.backBtnTheme != null ) {\n\t\t\t\tthis.element\n\t\t\t\t\t.find( \".ui-toolbar-back-btn\" )\n\t\t\t\t\t.addClass( \"ui-btn ui-btn-\" + o.backBtnTheme );\n\t\t\t}\n\t\t\tif ( o.backBtnText !== undefined ) {\n\t\t\t\tthis.element.find( \".ui-toolbar-back-btn .ui-btn-text\" ).text( o.backBtnText );\n\t\t\t}\n\t\t\tif ( o.theme !== undefined ) {\n\t\t\t\tvar currentTheme = this.options.theme ? this.options.theme : \"inherit\",\n\t\t\t\t\tnewTheme = o.theme ? o.theme : \"inherit\";\n\n\t\t\t\tthis.element.removeClass( \"ui-bar-\" + currentTheme ).addClass( \"ui-bar-\" + newTheme );\n\t\t\t}\n\n\t\t\tthis._super( o );\n\t\t},\n\t\trefresh: function() {\n\t\t\tif ( this.role === \"header\" ) {\n\t\t\t\tthis._addHeaderButtonClasses();\n\t\t\t}\n\t\t\tif ( !this.page ) {\n\t\t\t\tthis._setRelative();\n\t\t\t\tif ( this.role === \"footer\" ) {\n\t\t\t\t\tthis.element.appendTo( \"body\" );\n\t\t\t\t} else if ( this.role === \"header\" ) {\n\t\t\t\t\tthis._updateBackButton();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._addHeadingClasses();\n\t\t\tthis._btnMarkup();\n\t\t},\n\n\t\t//we only want this to run on non fixed toolbars so make it easy to override\n\t\t_setRelative: function() {\n\t\t\t$( \"[data-\"+ $.mobile.ns + \"role='page']\" ).css({ \"position\": \"relative\" });\n\t\t},\n\n\t\t// Deprecated in 1.4. As from 1.5 button classes have to be present in the markup.\n\t\t_btnMarkup: function() {\n\t\t\tthis.element\n\t\t\t\t.children( \"a\" )\n\t\t\t\t.filter( \":not([data-\" + $.mobile.ns + \"role='none'])\" )\n\t\t\t\t.attr( \"data-\" + $.mobile.ns + \"role\", \"button\" );\n\t\t\tthis.element.trigger( \"create\" );\n\t\t},\n\t\t// Deprecated in 1.4. As from 1.5 ui-btn-left/right classes have to be present in the markup.\n\t\t_addHeaderButtonClasses: function() {\n\t\t\tvar headerAnchors = this.element.children( \"a, button\" );\n\n\t\t\t// Do not mistake a back button for a left toolbar button\n\t\t\tthis.leftbtn = headerAnchors.hasClass( \"ui-btn-left\" ) &&\n\t\t\t\t!headerAnchors.hasClass( \"ui-toolbar-back-btn\" );\n\n\t\t\tthis.rightbtn = headerAnchors.hasClass( \"ui-btn-right\" );\n\n\t\t\t// Filter out right buttons and back buttons\n\t\t\tthis.leftbtn = this.leftbtn ||\n\t\t\t\theaderAnchors.eq( 0 )\n\t\t\t\t\t.not( \".ui-btn-right,.ui-toolbar-back-btn\" )\n\t\t\t\t\t.addClass( \"ui-btn-left\" )\n\t\t\t\t\t.length;\n\n\t\t\tthis.rightbtn = this.rightbtn || headerAnchors.eq( 1 ).addClass( \"ui-btn-right\" ).length;\n\t\t},\n\t\t_updateBackButton: function() {\n\t\t\tvar backButton,\n\t\t\t\toptions = this.options,\n\t\t\t\ttheme = options.backBtnTheme || options.theme;\n\n\t\t\t// Retrieve the back button or create a new, empty one\n\t\t\tbackButton = this._backButton = ( this._backButton || {} );\n\n\t\t\t// We add a back button only if the option to do so is on\n\t\t\tif ( this.options.addBackBtn &&\n\n\t\t\t\t\t// This must also be a header toolbar\n\t\t\t\t\tthis.role === \"header\" &&\n\n\t\t\t\t\t// There must be multiple pages in the DOM\n\t\t\t\t\t$( \".ui-page\" ).length > 1 &&\n\t\t\t\t\t( this.page ?\n\n\t\t\t\t\t\t// If the toolbar is internal the page's URL must differ from the hash\n\t\t\t\t\t\t( this.page[ 0 ].getAttribute( \"data-\" + $.mobile.ns + \"url\" ) !==\n\t\t\t\t\t\t\t$.mobile.path.stripHash( location.hash ) ) :\n\n\t\t\t\t\t\t// Otherwise, if the toolbar is external there must be at least one\n\t\t\t\t\t\t// history item to which one can go back\n\t\t\t\t\t\t( $.mobile.navigate && $.mobile.navigate.history &&\n\t\t\t\t\t\t\t$.mobile.navigate.history.activeIndex > 0 ) ) &&\n\n\t\t\t\t\t// The toolbar does not have a left button\n\t\t\t\t\t!this.leftbtn ) {\n\n\t\t\t\t// Skip back button creation if one is already present\n\t\t\t\tif ( !backButton.attached ) {\n\t\t\t\t\tthis.backButton = backButton.element = ( backButton.element ||\n\t\t\t\t\t\t$( \"<a role='button' href='javascript:void(0);' \" +\n\t\t\t\t\t\t\t\"class='ui-btn ui-corner-all ui-shadow ui-btn-left \" +\n\t\t\t\t\t\t\t\t( theme ? \"ui-btn-\" + theme + \" \" : \"\" ) +\n\t\t\t\t\t\t\t\t\"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' \" +\n\t\t\t\t\t\t\t\"data-\" + $.mobile.ns + \"rel='back'>\" + options.backBtnText +\n\t\t\t\t\t\t\t\"</a>\" ) )\n\t\t\t\t\t\t\t.prependTo( this.element );\n\t\t\t\t\tbackButton.attached = true;\n\t\t\t\t}\n\n\t\t\t// If we are not adding a back button, then remove the one present, if any\n\t\t\t} else if ( backButton.element ) {\n\t\t\t\tbackButton.element.detach();\n\t\t\t\tbackButton.attached = false;\n\t\t\t}\n\t\t},\n\t\t_addHeadingClasses: function() {\n\t\t\tthis.element.children( \"h1, h2, h3, h4, h5, h6\" )\n\t\t\t\t.addClass( \"ui-title\" )\n\t\t\t\t// Regardless of h element number in src, it becomes h1 for the enhanced page\n\t\t\t\t.attr({\n\t\t\t\t\t\"role\": \"heading\",\n\t\t\t\t\t\"aria-level\": \"1\"\n\t\t\t\t});\n\t\t},\n\t\t_destroy: function() {\n\t\t\tvar currentTheme;\n\n\t\t\tthis.element.children( \"h1, h2, h3, h4, h5, h6\" )\n\t\t\t\t.removeClass( \"ui-title\" )\n\t\t\t\t.removeAttr( \"role\" )\n\t\t\t\t.removeAttr( \"aria-level\" );\n\n\t\t\tif ( this.role === \"header\" ) {\n\t\t\t\tthis.element.children( \"a, button\" )\n\t\t\t\t\t.removeClass( \"ui-btn-left ui-btn-right ui-btn ui-shadow ui-corner-all\" );\n\t\t\t\tif ( this.backButton) {\n\t\t\t\t\tthis.backButton.remove();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrentTheme = this.options.theme ? this.options.theme : \"inherit\";\n\t\t\tthis.element.removeClass( \"ui-bar-\" + currentTheme );\n\n\t\t\tthis.element.removeClass( \"ui-\" + this.role ).removeAttr( \"role\" );\n\t\t}\n\t});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n\t$.widget( \"mobile.toolbar\", $.mobile.toolbar, {\n\t\toptions: {\n\t\t\tposition:null,\n\t\t\tvisibleOnPageShow: true,\n\t\t\tdisablePageZoom: true,\n\t\t\ttransition: \"slide\", //can be none, fade, slide (slide maps to slideup or slidedown)\n\t\t\tfullscreen: false,\n\t\t\ttapToggle: true,\n\t\t\ttapToggleBlacklist: \"a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-flipswitch, .ui-popup, .ui-panel, .ui-panel-dismiss-open\",\n\t\t\thideDuringFocus: \"input, textarea, select\",\n\t\t\tupdatePagePadding: true,\n\t\t\ttrackPersistentToolbars: true,\n\n\t\t\t// Browser detection! Weeee, here we go...\n\t\t\t// Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.\n\t\t\t// Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.\n\t\t\t// Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window\n\t\t\t// The following function serves to rule out some popular browsers with known fixed-positioning issues\n\t\t\t// This is a plugin option like any other, so feel free to improve or overwrite it\n\t\t\tsupportBlacklist: function() {\n\t\t\t\treturn !$.support.fixedPosition;\n\t\t\t}\n\t\t},\n\n\t\t_create: function() {\n\t\t\tthis._super();\n\t\t\tthis.pagecontainer = $( \":mobile-pagecontainer\" );\n\t\t\tif ( this.options.position === \"fixed\" && !this.options.supportBlacklist() ) {\n\t\t\t\tthis._makeFixed();\n\t\t\t}\n\t\t},\n\n\t\t_makeFixed: function() {\n\t\t\tthis.element.addClass( \"ui-\"+ this.role +\"-fixed\" );\n\t\t\tthis.updatePagePadding();\n\t\t\tthis._addTransitionClass();\n\t\t\tthis._bindPageEvents();\n\t\t\tthis._bindToggleHandlers();\n\t\t},\n\n\t\t_setOptions: function( o ) {\n\t\t\tif ( o.position === \"fixed\" && this.options.position !== \"fixed\" ) {\n\t\t\t\tthis._makeFixed();\n\t\t\t}\n\t\t\tif ( this.options.position === \"fixed\" && !this.options.supportBlacklist() ) {\n\t\t\t\tvar $page = ( !!this.page )? this.page: ( $(\".ui-page-active\").length > 0 )? $(\".ui-page-active\"): $(\".ui-page\").eq(0);\n\n\t\t\t\tif ( o.fullscreen !== undefined) {\n\t\t\t\t\tif ( o.fullscreen ) {\n\t\t\t\t\t\tthis.element.addClass( \"ui-\"+ this.role +\"-fullscreen\" );\n\t\t\t\t\t\t$page.addClass( \"ui-page-\" + this.role + \"-fullscreen\" );\n\t\t\t\t\t}\n\t\t\t\t\t// If not fullscreen, add class to page to set top or bottom padding\n\t\t\t\t\telse {\n\t\t\t\t\t\tthis.element.removeClass( \"ui-\"+ this.role +\"-fullscreen\" );\n\t\t\t\t\t\t$page.removeClass( \"ui-page-\" + this.role + \"-fullscreen\" ).addClass( \"ui-page-\" + this.role+ \"-fixed\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._super(o);\n\t\t},\n\n\t\t_addTransitionClass: function() {\n\t\t\tvar tclass = this.options.transition;\n\n\t\t\tif ( tclass && tclass !== \"none\" ) {\n\t\t\t\t// use appropriate slide for header or footer\n\t\t\t\tif ( tclass === \"slide\" ) {\n\t\t\t\t\ttclass = this.element.hasClass( \"ui-header\" ) ? \"slidedown\" : \"slideup\";\n\t\t\t\t}\n\n\t\t\t\tthis.element.addClass( tclass );\n\t\t\t}\n\t\t},\n\n\t\t_bindPageEvents: function() {\n\t\t\tvar page = ( !!this.page )? this.element.closest( \".ui-page\" ): this.document;\n\t\t\t//page event bindings\n\t\t\t// Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up\n\t\t\t// This method is meant to disable zoom while a fixed-positioned toolbar page is visible\n\t\t\tthis._on( page , {\n\t\t\t\t\"pagebeforeshow\": \"_handlePageBeforeShow\",\n\t\t\t\t\"webkitAnimationStart\":\"_handleAnimationStart\",\n\t\t\t\t\"animationstart\":\"_handleAnimationStart\",\n\t\t\t\t\"updatelayout\": \"_handleAnimationStart\",\n\t\t\t\t\"pageshow\": \"_handlePageShow\",\n\t\t\t\t\"pagebeforehide\": \"_handlePageBeforeHide\"\n\t\t\t});\n\t\t},\n\n\t\t_handlePageBeforeShow: function( ) {\n\t\t\tvar o = this.options;\n\t\t\tif ( o.disablePageZoom ) {\n\t\t\t\t$.mobile.zoom.disable( true );\n\t\t\t}\n\t\t\tif ( !o.visibleOnPageShow ) {\n\t\t\t\tthis.hide( true );\n\t\t\t}\n\t\t},\n\n\t\t_handleAnimationStart: function() {\n\t\t\tif ( this.options.updatePagePadding ) {\n\t\t\t\tthis.updatePagePadding( ( !!this.page )? this.page: \".ui-page-active\" );\n\t\t\t}\n\t\t},\n\n\t\t_handlePageShow: function() {\n\t\t\tthis.updatePagePadding( ( !!this.page )? this.page: \".ui-page-active\" );\n\t\t\tif ( this.options.updatePagePadding ) {\n\t\t\t\tthis._on( this.window, { \"throttledresize\": \"updatePagePadding\" } );\n\t\t\t}\n\t\t},\n\n\t\t_handlePageBeforeHide: function( e, ui ) {\n\t\t\tvar o = this.options,\n\t\t\t\tthisFooter, thisHeader, nextFooter, nextHeader;\n\n\t\t\tif ( o.disablePageZoom ) {\n\t\t\t\t$.mobile.zoom.enable( true );\n\t\t\t}\n\t\t\tif ( o.updatePagePadding ) {\n\t\t\t\tthis._off( this.window, \"throttledresize\" );\n\t\t\t}\n\n\t\t\tif ( o.trackPersistentToolbars ) {\n\t\t\t\tthisFooter = $( \".ui-footer-fixed:jqmData(id)\", this.page );\n\t\t\t\tthisHeader = $( \".ui-header-fixed:jqmData(id)\", this.page );\n\t\t\t\tnextFooter = thisFooter.length && ui.nextPage && $( \".ui-footer-fixed:jqmData(id='\" + thisFooter.jqmData( \"id\" ) + \"')\", ui.nextPage ) || $();\n\t\t\t\tnextHeader = thisHeader.length && ui.nextPage && $( \".ui-header-fixed:jqmData(id='\" + thisHeader.jqmData( \"id\" ) + \"')\", ui.nextPage ) || $();\n\n\t\t\t\tif ( nextFooter.length || nextHeader.length ) {\n\n\t\t\t\t\tnextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );\n\n\t\t\t\t\tui.nextPage.one( \"pageshow\", function() {\n\t\t\t\t\t\tnextHeader.prependTo( this );\n\t\t\t\t\t\tnextFooter.appendTo( this );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_visible: true,\n\n\t\t// This will set the content element's top or bottom padding equal to the toolbar's height\n\t\tupdatePagePadding: function( tbPage ) {\n\t\t\tvar $el = this.element,\n\t\t\t\theader = ( this.role ===\"header\" ),\n\t\t\t\tpos = parseFloat( $el.css( header ? \"top\" : \"bottom\" ) );\n\n\t\t\t// This behavior only applies to \"fixed\", not \"fullscreen\"\n\t\t\tif ( this.options.fullscreen ) { return; }\n\t\t\t// tbPage argument can be a Page object or an event, if coming from throttled resize.\n\t\t\ttbPage = ( tbPage && tbPage.type === undefined && tbPage ) || this.page || $el.closest( \".ui-page\" );\n\t\t\ttbPage = ( !!this.page )? this.page: \".ui-page-active\";\n\t\t\t$( tbPage ).css( \"padding-\" + ( header ? \"top\" : \"bottom\" ), $el.outerHeight() + pos );\n\t\t},\n\n\t\t_useTransition: function( notransition ) {\n\t\t\tvar $win = this.window,\n\t\t\t\t$el = this.element,\n\t\t\t\tscroll = $win.scrollTop(),\n\t\t\t\telHeight = $el.height(),\n\t\t\t\tpHeight = ( !!this.page )? $el.closest( \".ui-page\" ).height():$(\".ui-page-active\").height(),\n\t\t\t\tviewportHeight = $.mobile.getScreenHeight();\n\n\t\t\treturn !notransition &&\n\t\t\t\t( this.options.transition && this.options.transition !== \"none\" &&\n\t\t\t\t(\n\t\t\t\t\t( this.role === \"header\" && !this.options.fullscreen && scroll > elHeight ) ||\n\t\t\t\t\t( this.role === \"footer\" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )\n\t\t\t\t) || this.options.fullscreen\n\t\t\t\t);\n\t\t},\n\n\t\tshow: function( notransition ) {\n\t\t\tvar hideClass = \"ui-fixed-hidden\",\n\t\t\t\t$el = this.element;\n\n\t\t\tif ( this._useTransition( notransition ) ) {\n\t\t\t\t$el\n\t\t\t\t\t.removeClass( \"out \" + hideClass )\n\t\t\t\t\t.addClass( \"in\" )\n\t\t\t\t\t.animationComplete(function () {\n\t\t\t\t\t\t$el.removeClass( \"in\" );\n\t\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\t$el.removeClass( hideClass );\n\t\t\t}\n\t\t\tthis._visible = true;\n\t\t},\n\n\t\thide: function( notransition ) {\n\t\t\tvar hideClass = \"ui-fixed-hidden\",\n\t\t\t\t$el = this.element,\n\t\t\t\t// if it's a slide transition, our new transitions need the reverse class as well to slide outward\n\t\t\t\toutclass = \"out\" + ( this.options.transition === \"slide\" ? \" reverse\" : \"\" );\n\n\t\t\tif ( this._useTransition( notransition ) ) {\n\t\t\t\t$el\n\t\t\t\t\t.addClass( outclass )\n\t\t\t\t\t.removeClass( \"in\" )\n\t\t\t\t\t.animationComplete(function() {\n\t\t\t\t\t\t$el.addClass( hideClass ).removeClass( outclass );\n\t\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\t$el.addClass( hideClass ).removeClass( outclass );\n\t\t\t}\n\t\t\tthis._visible = false;\n\t\t},\n\n\t\ttoggle: function() {\n\t\t\tthis[ this._visible ? \"hide\" : \"show\" ]();\n\t\t},\n\n\t\t_bindToggleHandlers: function() {\n\t\t\tvar self = this,\n\t\t\t\to = self.options,\n\t\t\t\tdelayShow, delayHide,\n\t\t\t\tisVisible = true,\n\t\t\t\tpage = ( !!this.page )? this.page: $(\".ui-page\");\n\n\t\t\t// tap toggle\n\t\t\tpage\n\t\t\t\t.bind( \"vclick\", function( e ) {\n\t\t\t\t\tif ( o.tapToggle && !$( e.target ).closest( o.tapToggleBlacklist ).length ) {\n\t\t\t\t\t\tself.toggle();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.bind( \"focusin focusout\", function( e ) {\n\t\t\t\t\t//this hides the toolbars on a keyboard pop to give more screen room and prevent ios bug which\n\t\t\t\t\t//positions fixed toolbars in the middle of the screen on pop if the input is near the top or\n\t\t\t\t\t//bottom of the screen addresses issues #4410 Footer navbar moves up when clicking on a textbox in an Android environment\n\t\t\t\t\t//and issue #4113 Header and footer change their position after keyboard popup - iOS\n\t\t\t\t\t//and issue #4410 Footer navbar moves up when clicking on a textbox in an Android environment\n\t\t\t\t\tif ( screen.width < 1025 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( \".ui-header-fixed, .ui-footer-fixed\" ).length ) {\n\t\t\t\t\t\t//Fix for issue #4724 Moving through form in Mobile Safari with \"Next\" and \"Previous\" system\n\t\t\t\t\t\t//controls causes fixed position, tap-toggle false Header to reveal itself\n\t\t\t\t\t\t// isVisible instead of self._visible because the focusin and focusout events fire twice at the same time\n\t\t\t\t\t\t// Also use a delay for hiding the toolbars because on Android native browser focusin is direclty followed\n\t\t\t\t\t\t// by a focusout when a native selects opens and the other way around when it closes.\n\t\t\t\t\t\tif ( e.type === \"focusout\" && !isVisible ) {\n\t\t\t\t\t\t\tisVisible = true;\n\t\t\t\t\t\t\t//wait for the stack to unwind and see if we have jumped to another input\n\t\t\t\t\t\t\tclearTimeout( delayHide );\n\t\t\t\t\t\t\tdelayShow = setTimeout( function() {\n\t\t\t\t\t\t\t\tself.show();\n\t\t\t\t\t\t\t}, 0 );\n\t\t\t\t\t\t} else if ( e.type === \"focusin\" && !!isVisible ) {\n\t\t\t\t\t\t\t//if we have jumped to another input clear the time out to cancel the show.\n\t\t\t\t\t\t\tclearTimeout( delayShow );\n\t\t\t\t\t\t\tisVisible = false;\n\t\t\t\t\t\t\tdelayHide = setTimeout( function() {\n\t\t\t\t\t\t\t\tself.hide();\n\t\t\t\t\t\t\t}, 0 );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t},\n\n\t\t_setRelative: function() {\n\t\t\tif( this.options.position !== \"fixed\" ){\n\t\t\t\t$( \"[data-\"+ $.mobile.ns + \"role='page']\" ).css({ \"position\": \"relative\" });\n\t\t\t}\n\t\t},\n\n\t\t_destroy: function() {\n\t\t\tvar pageClasses, toolbarClasses, hasFixed, header, hasFullscreen,\n\t\t\t\tpage = this.pagecontainer.pagecontainer( \"getActivePage\" );\n\n\t\t\tthis._super();\n\t\t\tif ( this.options.position === \"fixed\" ) {\n\t\t\t\thasFixed = $(  \"body>.ui-\" + this.role + \"-fixed\" )\n\t\t\t\t\t\t\t.add( page.find( \".ui-\" + this.options.role + \"-fixed\" ) )\n\t\t\t\t\t\t\t.not( this.element ).length > 0;\n\t\t\t\thasFullscreen = $(  \"body>.ui-\" + this.role + \"-fixed\" )\n\t\t\t\t\t\t\t.add( page.find( \".ui-\" + this.options.role + \"-fullscreen\" ) )\n\t\t\t\t\t\t\t.not( this.element ).length > 0;\n\t\t\t\ttoolbarClasses =  \"ui-header-fixed ui-footer-fixed ui-header-fullscreen in out\" +\n\t\t\t\t\t\" ui-footer-fullscreen fade slidedown slideup ui-fixed-hidden\";\n\t\t\t\tthis.element.removeClass( toolbarClasses );\n\t\t\t\tif ( !hasFullscreen ) {\n\t\t\t\t\tpageClasses = \"ui-page-\" + this.role + \"-fullscreen\";\n\t\t\t\t}\n\t\t\t\tif ( !hasFixed ) {\n\t\t\t\t\theader = this.role === \"header\";\n\t\t\t\t\tpageClasses += \" ui-page-\" + this.role + \"-fixed\";\n\t\t\t\t\tpage.css( \"padding-\" + ( header ? \"top\" : \"bottom\" ), \"\" );\n\t\t\t\t}\n\t\t\t\tpage.removeClass( pageClasses );\n\t\t\t}\n\t\t}\n\n\t});\n})( jQuery );\n\n(function( $, undefined ) {\n\t$.widget( \"mobile.toolbar\", $.mobile.toolbar, {\n\n\t\t_makeFixed: function() {\n\t\t\tthis._super();\n\t\t\tthis._workarounds();\n\t\t},\n\n\t\t//check the browser and version and run needed workarounds\n\t\t_workarounds: function() {\n\t\t\tvar ua = navigator.userAgent,\n\t\t\tplatform = navigator.platform,\n\t\t\t// Rendering engine is Webkit, and capture major version\n\t\t\twkmatch = ua.match( /AppleWebKit\\/([0-9]+)/ ),\n\t\t\twkversion = !!wkmatch && wkmatch[ 1 ],\n\t\t\tos = null,\n\t\t\tself = this;\n\t\t\t//set the os we are working in if it dosent match one with workarounds return\n\t\t\tif ( platform.indexOf( \"iPhone\" ) > -1 || platform.indexOf( \"iPad\" ) > -1  || platform.indexOf( \"iPod\" ) > -1 ) {\n\t\t\t\tos = \"ios\";\n\t\t\t} else if ( ua.indexOf( \"Android\" ) > -1 ) {\n\t\t\t\tos = \"android\";\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t//check os version if it dosent match one with workarounds return\n\t\t\tif ( os === \"ios\" ) {\n\t\t\t\t//iOS  workarounds\n\t\t\t\tself._bindScrollWorkaround();\n\t\t\t} else if ( os === \"android\" && wkversion && wkversion < 534 ) {\n\t\t\t\t//Android 2.3 run all Android 2.3 workaround\n\t\t\t\tself._bindScrollWorkaround();\n\t\t\t\tself._bindListThumbWorkaround();\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t},\n\n\t\t//Utility class for checking header and footer positions relative to viewport\n\t\t_viewportOffset: function() {\n\t\t\tvar $el = this.element,\n\t\t\t\theader = $el.hasClass( \"ui-header\" ),\n\t\t\t\toffset = Math.abs( $el.offset().top - this.window.scrollTop() );\n\t\t\tif ( !header ) {\n\t\t\t\toffset = Math.round( offset - this.window.height() + $el.outerHeight() ) - 60;\n\t\t\t}\n\t\t\treturn offset;\n\t\t},\n\n\t\t//bind events for _triggerRedraw() function\n\t\t_bindScrollWorkaround: function() {\n\t\t\tvar self = this;\n\t\t\t//bind to scrollstop and check if the toolbars are correctly positioned\n\t\t\tthis._on( this.window, { scrollstop: function() {\n\t\t\t\tvar viewportOffset = self._viewportOffset();\n\t\t\t\t//check if the header is visible and if its in the right place\n\t\t\t\tif ( viewportOffset > 2 && self._visible ) {\n\t\t\t\t\tself._triggerRedraw();\n\t\t\t\t}\n\t\t\t}});\n\t\t},\n\n\t\t//this addresses issue #4250 Persistent footer instability in v1.1 with long select lists in Android 2.3.3\n\t\t//and issue #3748 Android 2.x: Page transitions broken when fixed toolbars used\n\t\t//the absolutely positioned thumbnail in a list view causes problems with fixed position buttons above in a nav bar\n\t\t//setting the li's to -webkit-transform:translate3d(0,0,0); solves this problem to avoide potential issues in other\n\t\t//platforms we scope this with the class ui-android-2x-fix\n\t\t_bindListThumbWorkaround: function() {\n\t\t\tthis.element.closest( \".ui-page\" ).addClass( \"ui-android-2x-fixed\" );\n\t\t},\n\t\t//this addresses issues #4337 Fixed header problem after scrolling content on iOS and Android\n\t\t//and device bugs project issue #1 Form elements can lose click hit area in position: fixed containers.\n\t\t//this also addresses not on fixed toolbars page in docs\n\t\t//adding 1px of padding to the bottom then removing it causes a \"redraw\"\n\t\t//which positions the toolbars correctly (they will always be visually correct)\n\t\t_triggerRedraw: function() {\n\t\t\tvar paddingBottom = parseFloat( $( \".ui-page-active\" ).css( \"padding-bottom\" ) );\n\t\t\t//trigger page redraw to fix incorrectly positioned fixed elements\n\t\t\t$( \".ui-page-active\" ).css( \"padding-bottom\", ( paddingBottom + 1 ) + \"px\" );\n\t\t\t//if the padding is reset with out a timeout the reposition will not occure.\n\t\t\t//this is independant of JQM the browser seems to need the time to react.\n\t\t\tsetTimeout( function() {\n\t\t\t\t$( \".ui-page-active\" ).css( \"padding-bottom\", paddingBottom + \"px\" );\n\t\t\t}, 0 );\n\t\t},\n\n\t\tdestroy: function() {\n\t\t\tthis._super();\n\t\t\t//Remove the class we added to the page previously in android 2.x\n\t\t\tthis.element.closest( \".ui-page-active\" ).removeClass( \"ui-android-2x-fix\" );\n\t\t}\n\t});\n\n})( jQuery );\n\n\n( function( $, undefined ) {\n\nvar ieHack = ( $.mobile.browser.oldIE && $.mobile.browser.oldIE <= 8 ),\n\tuiTemplate = $(\n\t\t\"<div class='ui-popup-arrow-guide'></div>\" +\n\t\t\"<div class='ui-popup-arrow-container\" + ( ieHack ? \" ie\" : \"\" ) + \"'>\" +\n\t\t\t\"<div class='ui-popup-arrow'></div>\" +\n\t\t\"</div>\"\n\t);\n\nfunction getArrow() {\n\tvar clone = uiTemplate.clone(),\n\t\tgd = clone.eq( 0 ),\n\t\tct = clone.eq( 1 ),\n\t\tar = ct.children();\n\n\treturn { arEls: ct.add( gd ), gd: gd, ct: ct, ar: ar };\n}\n\n$.widget( \"mobile.popup\", $.mobile.popup, {\n\toptions: {\n\n\t\tarrow: \"\"\n\t},\n\n\t_create: function() {\n\t\tvar ar,\n\t\t\tret = this._super();\n\n\t\tif ( this.options.arrow ) {\n\t\t\tthis._ui.arrow = ar = this._addArrow();\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t_addArrow: function() {\n\t\tvar theme,\n\t\t\topts = this.options,\n\t\t\tar = getArrow();\n\n\t\ttheme = this._themeClassFromOption( \"ui-body-\", opts.theme );\n\t\tar.ar.addClass( theme + ( opts.shadow ? \" ui-overlay-shadow\" : \"\" ) );\n\t\tar.arEls.hide().appendTo( this.element );\n\n\t\treturn ar;\n\t},\n\n\t_unenhance: function() {\n\t\tvar ar = this._ui.arrow;\n\n\t\tif ( ar ) {\n\t\t\tar.arEls.remove();\n\t\t}\n\n\t\treturn this._super();\n\t},\n\n\t// Pretend to show an arrow described by @p and @dir and calculate the\n\t// distance from the desired point. If a best-distance is passed in, return\n\t// the minimum of the one passed in and the one calculated.\n\t_tryAnArrow: function( p, dir, desired, s, best ) {\n\t\tvar result, r, diff, desiredForArrow = {}, tip = {};\n\n\t\t// If the arrow has no wiggle room along the edge of the popup, it cannot\n\t\t// be displayed along the requested edge without it sticking out.\n\t\tif ( s.arFull[ p.dimKey ] > s.guideDims[ p.dimKey ] ) {\n\t\t\treturn best;\n\t\t}\n\n\t\tdesiredForArrow[ p.fst ] = desired[ p.fst ] +\n\t\t\t( s.arHalf[ p.oDimKey ] + s.menuHalf[ p.oDimKey ] ) * p.offsetFactor -\n\t\t\ts.contentBox[ p.fst ] + ( s.clampInfo.menuSize[ p.oDimKey ] - s.contentBox[ p.oDimKey ] ) * p.arrowOffsetFactor;\n\t\tdesiredForArrow[ p.snd ] = desired[ p.snd ];\n\n\t\tresult = s.result || this._calculateFinalLocation( desiredForArrow, s.clampInfo );\n\t\tr = { x: result.left, y: result.top };\n\n\t\ttip[ p.fst ] = r[ p.fst ] + s.contentBox[ p.fst ] + p.tipOffset;\n\t\ttip[ p.snd ] = Math.max( result[ p.prop ] + s.guideOffset[ p.prop ] + s.arHalf[ p.dimKey ],\n\t\t\tMath.min( result[ p.prop ] + s.guideOffset[ p.prop ] + s.guideDims[ p.dimKey ] - s.arHalf[ p.dimKey ],\n\t\t\t\tdesired[ p.snd ] ) );\n\n\t\tdiff = Math.abs( desired.x - tip.x ) + Math.abs( desired.y - tip.y );\n\t\tif ( !best || diff < best.diff ) {\n\t\t\t// Convert tip offset to coordinates inside the popup\n\t\t\ttip[ p.snd ] -= s.arHalf[ p.dimKey ] + result[ p.prop ] + s.contentBox[ p.snd ];\n\t\t\tbest = { dir: dir, diff: diff, result: result, posProp: p.prop, posVal: tip[ p.snd ] };\n\t\t}\n\n\t\treturn best;\n\t},\n\n\t_getPlacementState: function( clamp ) {\n\t\tvar offset, gdOffset,\n\t\t\tar = this._ui.arrow,\n\t\t\tstate = {\n\t\t\t\tclampInfo: this._clampPopupWidth( !clamp ),\n\t\t\t\tarFull: { cx: ar.ct.width(), cy: ar.ct.height() },\n\t\t\t\tguideDims: { cx: ar.gd.width(), cy: ar.gd.height() },\n\t\t\t\tguideOffset: ar.gd.offset()\n\t\t\t};\n\n\t\toffset = this.element.offset();\n\n\t\tar.gd.css( { left: 0, top: 0, right: 0, bottom: 0 } );\n\t\tgdOffset = ar.gd.offset();\n\t\tstate.contentBox = {\n\t\t\tx: gdOffset.left - offset.left,\n\t\t\ty: gdOffset.top - offset.top,\n\t\t\tcx: ar.gd.width(),\n\t\t\tcy: ar.gd.height()\n\t\t};\n\t\tar.gd.removeAttr( \"style\" );\n\n\t\t// The arrow box moves between guideOffset and guideOffset + guideDims - arFull\n\t\tstate.guideOffset = { left: state.guideOffset.left - offset.left, top: state.guideOffset.top - offset.top };\n\t\tstate.arHalf = { cx: state.arFull.cx / 2, cy: state.arFull.cy / 2 };\n\t\tstate.menuHalf = { cx: state.clampInfo.menuSize.cx / 2, cy: state.clampInfo.menuSize.cy / 2 };\n\n\t\treturn state;\n\t},\n\n\t_placementCoords: function( desired ) {\n\t\tvar state, best, params, elOffset, bgRef,\n\t\t\toptionValue = this.options.arrow,\n\t\t\tar = this._ui.arrow;\n\n\t\tif ( !ar ) {\n\t\t\treturn this._super( desired );\n\t\t}\n\n\t\tar.arEls.show();\n\n\t\tbgRef = {};\n\t\tstate = this._getPlacementState( true );\n\t\tparams = {\n\t\t\t\"l\": { fst: \"x\", snd: \"y\", prop: \"top\", dimKey: \"cy\", oDimKey: \"cx\", offsetFactor: 1, tipOffset:  -state.arHalf.cx, arrowOffsetFactor: 0 },\n\t\t\t\"r\": { fst: \"x\", snd: \"y\", prop: \"top\", dimKey: \"cy\", oDimKey: \"cx\", offsetFactor: -1, tipOffset: state.arHalf.cx + state.contentBox.cx, arrowOffsetFactor: 1 },\n\t\t\t\"b\": { fst: \"y\", snd: \"x\", prop: \"left\", dimKey: \"cx\", oDimKey: \"cy\", offsetFactor: -1, tipOffset: state.arHalf.cy + state.contentBox.cy, arrowOffsetFactor: 1 },\n\t\t\t\"t\": { fst: \"y\", snd: \"x\", prop: \"left\", dimKey: \"cx\", oDimKey: \"cy\", offsetFactor: 1, tipOffset: -state.arHalf.cy, arrowOffsetFactor: 0 }\n\t\t};\n\n\t\t// Try each side specified in the options to see on which one the arrow\n\t\t// should be placed such that the distance between the tip of the arrow and\n\t\t// the desired coordinates is the shortest.\n\t\t$.each( ( optionValue === true ? \"l,t,r,b\" : optionValue ).split( \",\" ),\n\t\t\t$.proxy( function( key, value ) {\n\t\t\t\tbest = this._tryAnArrow( params[ value ], value, desired, state, best );\n\t\t\t}, this ) );\n\n\t\t// Could not place the arrow along any of the edges - behave as if showing\n\t\t// the arrow was turned off.\n\t\tif ( !best ) {\n\t\t\tar.arEls.hide();\n\t\t\treturn this._super( desired );\n\t\t}\n\n\t\t// Move the arrow into place\n\t\tar.ct\n\t\t\t.removeClass( \"ui-popup-arrow-l ui-popup-arrow-t ui-popup-arrow-r ui-popup-arrow-b\" )\n\t\t\t.addClass( \"ui-popup-arrow-\" + best.dir )\n\t\t\t.removeAttr( \"style\" ).css( best.posProp, best.posVal )\n\t\t\t.show();\n\n\t\t// Do not move/size the background div on IE, because we use the arrow div for background as well.\n\t\tif ( !ieHack ) {\n\t\t\telOffset = this.element.offset();\n\t\t\tbgRef[ params[ best.dir ].fst ] = ar.ct.offset();\n\t\t\tbgRef[ params[ best.dir ].snd ] = {\n\t\t\t\tleft: elOffset.left + state.contentBox.x,\n\t\t\t\ttop: elOffset.top + state.contentBox.y\n\t\t\t};\n\t\t}\n\n\t\treturn best.result;\n\t},\n\n\t_setOptions: function( opts ) {\n\t\tvar newTheme,\n\t\t\toldTheme = this.options.theme,\n\t\t\tar = this._ui.arrow,\n\t\t\tret = this._super( opts );\n\n\t\tif ( opts.arrow !== undefined ) {\n\t\t\tif ( !ar && opts.arrow ) {\n\t\t\t\tthis._ui.arrow = this._addArrow();\n\n\t\t\t\t// Important to return here so we don't set the same options all over\n\t\t\t\t// again below.\n\t\t\t\treturn;\n\t\t\t} else if ( ar && !opts.arrow ) {\n\t\t\t\tar.arEls.remove();\n\t\t\t\tthis._ui.arrow = null;\n\t\t\t}\n\t\t}\n\n\t\t// Reassign with potentially new arrow\n\t\tar = this._ui.arrow;\n\n\t\tif ( ar ) {\n\t\t\tif ( opts.theme !== undefined ) {\n\t\t\t\toldTheme = this._themeClassFromOption( \"ui-body-\", oldTheme );\n\t\t\t\tnewTheme = this._themeClassFromOption( \"ui-body-\", opts.theme );\n\t\t\t\tar.ar.removeClass( oldTheme ).addClass( newTheme );\n\t\t\t}\n\n\t\t\tif ( opts.shadow !== undefined ) {\n\t\t\t\tar.ar.toggleClass( \"ui-overlay-shadow\", opts.shadow );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t_destroy: function() {\n\t\tvar ar = this._ui.arrow;\n\n\t\tif ( ar ) {\n\t\t\tar.arEls.remove();\n\t\t}\n\n\t\treturn this._super();\n\t}\n});\n\n})( jQuery );\n\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.panel\", {\n\toptions: {\n\t\tclasses: {\n\t\t\tpanel: \"ui-panel\",\n\t\t\tpanelOpen: \"ui-panel-open\",\n\t\t\tpanelClosed: \"ui-panel-closed\",\n\t\t\tpanelFixed: \"ui-panel-fixed\",\n\t\t\tpanelInner: \"ui-panel-inner\",\n\t\t\tmodal: \"ui-panel-dismiss\",\n\t\t\tmodalOpen: \"ui-panel-dismiss-open\",\n\t\t\tpageContainer: \"ui-panel-page-container\",\n\t\t\tpageWrapper: \"ui-panel-wrapper\",\n\t\t\tpageFixedToolbar: \"ui-panel-fixed-toolbar\",\n\t\t\tpageContentPrefix: \"ui-panel-page-content\", /* Used for wrapper and fixed toolbars position, display and open classes. */\n\t\t\tanimate: \"ui-panel-animate\"\n\t\t},\n\t\tanimate: true,\n\t\ttheme: null,\n\t\tposition: \"left\",\n\t\tdismissible: true,\n\t\tdisplay: \"reveal\", //accepts reveal, push, overlay\n\t\tswipeClose: true,\n\t\tpositionFixed: false\n\t},\n\n\t_closeLink: null,\n\t_parentPage: null,\n\t_page: null,\n\t_modal: null,\n\t_panelInner: null,\n\t_wrapper: null,\n\t_fixedToolbars: null,\n\n\t_create: function() {\n\t\tvar el = this.element,\n\t\t\tparentPage = el.closest( \".ui-page, :jqmData(role='page')\" );\n\n\t\t// expose some private props to other methods\n\t\t$.extend( this, {\n\t\t\t_closeLink: el.find( \":jqmData(rel='close')\" ),\n\t\t\t_parentPage: ( parentPage.length > 0 ) ? parentPage : false,\n\t\t\t_openedPage: null,\n\t\t\t_page: this._getPage,\n\t\t\t_panelInner: this._getPanelInner(),\n\t\t\t_fixedToolbars: this._getFixedToolbars\n\t\t});\n\t\tif ( this.options.display !== \"overlay\" ){\n\t\t\tthis._getWrapper();\n\t\t}\n\t\tthis._addPanelClasses();\n\n\t\t// if animating, add the class to do so\n\t\tif ( $.support.cssTransform3d && !!this.options.animate ) {\n\t\t\tthis.element.addClass( this.options.classes.animate );\n\t\t}\n\n\t\tthis._bindUpdateLayout();\n\t\tthis._bindCloseEvents();\n\t\tthis._bindLinkListeners();\n\t\tthis._bindPageEvents();\n\n\t\tif ( !!this.options.dismissible ) {\n\t\t\tthis._createModal();\n\t\t}\n\n\t\tthis._bindSwipeEvents();\n\t},\n\n\t_getPanelInner: function() {\n\t\tvar panelInner = this.element.find( \".\" + this.options.classes.panelInner );\n\n\t\tif ( panelInner.length === 0 ) {\n\t\t\tpanelInner = this.element.children().wrapAll( \"<div class='\" + this.options.classes.panelInner + \"' />\" ).parent();\n\t\t}\n\n\t\treturn panelInner;\n\t},\n\n\t_createModal: function() {\n\t\tvar self = this,\n\t\t\ttarget = self._parentPage ? self._parentPage.parent() : self.element.parent();\n\n\t\tself._modal = $( \"<div class='\" + self.options.classes.modal + \"'></div>\" )\n\t\t\t.on( \"mousedown\", function() {\n\t\t\t\tself.close();\n\t\t\t})\n\t\t\t.appendTo( target );\n\t},\n\n\t_getPage: function() {\n\t\tvar page = this._openedPage || this._parentPage || $( \".\" + $.mobile.activePageClass );\n\n\t\treturn page;\n\t},\n\n\t_getWrapper: function() {\n\t\tvar wrapper = this._page().find( \".\" + this.options.classes.pageWrapper );\n\t\tif ( wrapper.length === 0 ) {\n\t\t\twrapper = this._page().children( \".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)\" )\n\t\t\t\t.wrapAll( \"<div class='\" + this.options.classes.pageWrapper + \"'></div>\" )\n\t\t\t\t.parent();\n\t\t}\n\n\t\tthis._wrapper = wrapper;\n\t},\n\n\t_getFixedToolbars: function() {\n\t\tvar extFixedToolbars = $( \"body\" ).children( \".ui-header-fixed, .ui-footer-fixed\" ),\n\t\t\tintFixedToolbars = this._page().find( \".ui-header-fixed, .ui-footer-fixed\" ),\n\t\t\tfixedToolbars = extFixedToolbars.add( intFixedToolbars ).addClass( this.options.classes.pageFixedToolbar );\n\n\t\treturn fixedToolbars;\n\t},\n\n\t_getPosDisplayClasses: function( prefix ) {\n\t\treturn prefix + \"-position-\" + this.options.position + \" \" + prefix + \"-display-\" + this.options.display;\n\t},\n\n\t_getPanelClasses: function() {\n\t\tvar panelClasses = this.options.classes.panel +\n\t\t\t\" \" + this._getPosDisplayClasses( this.options.classes.panel ) +\n\t\t\t\" \" + this.options.classes.panelClosed +\n\t\t\t\" \" + \"ui-body-\" + ( this.options.theme ? this.options.theme : \"inherit\" );\n\n\t\tif ( !!this.options.positionFixed ) {\n\t\t\tpanelClasses += \" \" + this.options.classes.panelFixed;\n\t\t}\n\n\t\treturn panelClasses;\n\t},\n\n\t_addPanelClasses: function() {\n\t\tthis.element.addClass( this._getPanelClasses() );\n\t},\n\n\t_handleCloseClick: function( event ) {\n\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\tthis.close();\n\t\t}\n\t},\n\n\t_bindCloseEvents: function() {\n\t\tthis._on( this._closeLink, {\n\t\t\t\"click\": \"_handleCloseClick\"\n\t\t});\n\n\t\tthis._on({\n\t\t\t\"click a:jqmData(ajax='false')\": \"_handleCloseClick\"\n\t\t});\n\t},\n\n\t_positionPanel: function( scrollToTop ) {\n\t\tvar self = this,\n\t\t\tpanelInnerHeight = self._panelInner.outerHeight(),\n\t\t\texpand = panelInnerHeight > $.mobile.getScreenHeight();\n\n\t\tif ( expand || !self.options.positionFixed ) {\n\t\t\tif ( expand ) {\n\t\t\t\tself._unfixPanel();\n\t\t\t\t$.mobile.resetActivePageHeight( panelInnerHeight );\n\t\t\t}\n\t\t\tif ( scrollToTop ) {\n\t\t\t\tthis.window[ 0 ].scrollTo( 0, $.mobile.defaultHomeScroll );\n\t\t\t}\n\t\t} else {\n\t\t\tself._fixPanel();\n\t\t}\n\t},\n\n\t_bindFixListener: function() {\n\t\tthis._on( $( window ), { \"throttledresize\": \"_positionPanel\" });\n\t},\n\n\t_unbindFixListener: function() {\n\t\tthis._off( $( window ), \"throttledresize\" );\n\t},\n\n\t_unfixPanel: function() {\n\t\tif ( !!this.options.positionFixed && $.support.fixedPosition ) {\n\t\t\tthis.element.removeClass( this.options.classes.panelFixed );\n\t\t}\n\t},\n\n\t_fixPanel: function() {\n\t\tif ( !!this.options.positionFixed && $.support.fixedPosition ) {\n\t\t\tthis.element.addClass( this.options.classes.panelFixed );\n\t\t}\n\t},\n\n\t_bindUpdateLayout: function() {\n\t\tvar self = this;\n\n\t\tself.element.on( \"updatelayout\", function(/* e */) {\n\t\t\tif ( self._open ) {\n\t\t\t\tself._positionPanel();\n\t\t\t}\n\t\t});\n\t},\n\n\t_bindLinkListeners: function() {\n\t\tthis._on( \"body\", {\n\t\t\t\"click a\": \"_handleClick\"\n\t\t});\n\n\t},\n\n\t_handleClick: function( e ) {\n\t\tvar link,\n\t\t\tpanelId = this.element.attr( \"id\" );\n\n\t\tif ( e.currentTarget.href.split( \"#\" )[ 1 ] === panelId && panelId !== undefined ) {\n\n\t\t\te.preventDefault();\n\t\t\tlink = $( e.target );\n\t\t\tif ( link.hasClass( \"ui-btn\" ) ) {\n\t\t\t\tlink.addClass( $.mobile.activeBtnClass );\n\t\t\t\tthis.element.one( \"panelopen panelclose\", function() {\n\t\t\t\t\tlink.removeClass( $.mobile.activeBtnClass );\n\t\t\t\t});\n\t\t\t}\n\t\t\tthis.toggle();\n\t\t}\n\t},\n\n\t_bindSwipeEvents: function() {\n\t\tvar self = this,\n\t\t\tarea = self._modal ? self.element.add( self._modal ) : self.element;\n\n\t\t// on swipe, close the panel\n\t\tif ( !!self.options.swipeClose ) {\n\t\t\tif ( self.options.position === \"left\" ) {\n\t\t\t\tarea.on( \"swipeleft.panel\", function(/* e */) {\n\t\t\t\t\tself.close();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tarea.on( \"swiperight.panel\", function(/* e */) {\n\t\t\t\t\tself.close();\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n\n\t_bindPageEvents: function() {\n\t\tvar self = this;\n\n\t\tthis.document\n\t\t\t// Close the panel if another panel on the page opens\n\t\t\t.on( \"panelbeforeopen\", function( e ) {\n\t\t\t\tif ( self._open && e.target !== self.element[ 0 ] ) {\n\t\t\t\t\tself.close();\n\t\t\t\t}\n\t\t\t})\n\t\t\t// On escape, close? might need to have a target check too...\n\t\t\t.on( \"keyup.panel\", function( e ) {\n\t\t\t\tif ( e.keyCode === 27 && self._open ) {\n\t\t\t\t\tself.close();\n\t\t\t\t}\n\t\t\t});\n\t\tif ( !this._parentPage && this.options.display !== \"overlay\" ) {\n\t\t\tthis._on( this.document, {\n\t\t\t\t\"pageshow\": function() {\n\t\t\t\t\tthis._openedPage = null;\n\t\t\t\t\tthis._getWrapper();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t// Clean up open panels after page hide\n\t\tif ( self._parentPage ) {\n\t\t\tthis.document.on( \"pagehide\", \":jqmData(role='page')\", function() {\n\t\t\t\tif ( self._open ) {\n\t\t\t\t\tself.close( true );\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.document.on( \"pagebeforehide\", function() {\n\t\t\t\tif ( self._open ) {\n\t\t\t\t\tself.close( true );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\t// state storage of open or closed\n\t_open: false,\n\t_pageContentOpenClasses: null,\n\t_modalOpenClasses: null,\n\n\topen: function( immediate ) {\n\t\tif ( !this._open ) {\n\t\t\tvar self = this,\n\t\t\t\to = self.options,\n\n\t\t\t\t_openPanel = function() {\n\t\t\t\t\tself._off( self.document , \"panelclose\" );\n\t\t\t\t\tself._page().jqmData( \"panel\", \"open\" );\n\n\t\t\t\t\tif ( $.support.cssTransform3d && !!o.animate && o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._wrapper.addClass( o.classes.animate );\n\t\t\t\t\t\tself._fixedToolbars().addClass( o.classes.animate );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !immediate && $.support.cssTransform3d && !!o.animate ) {\n\t\t\t\t\t\t( self._wrapper || self.element )\n\t\t\t\t\t\t\t.animationComplete( complete, \"transition\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetTimeout( complete, 0 );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( o.theme && o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._page().parent()\n\t\t\t\t\t\t\t.addClass( o.classes.pageContainer + \"-themed \" + o.classes.pageContainer + \"-\" + o.theme );\n\t\t\t\t\t}\n\n\t\t\t\t\tself.element\n\t\t\t\t\t\t.removeClass( o.classes.panelClosed )\n\t\t\t\t\t\t.addClass( o.classes.panelOpen );\n\n\t\t\t\t\tself._positionPanel( true );\n\n\t\t\t\t\tself._pageContentOpenClasses = self._getPosDisplayClasses( o.classes.pageContentPrefix );\n\n\t\t\t\t\tif ( o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._page().parent().addClass( o.classes.pageContainer );\n\t\t\t\t\t\tself._wrapper.addClass( self._pageContentOpenClasses );\n\t\t\t\t\t\tself._fixedToolbars().addClass( self._pageContentOpenClasses );\n\t\t\t\t\t}\n\n\t\t\t\t\tself._modalOpenClasses = self._getPosDisplayClasses( o.classes.modal ) + \" \" + o.classes.modalOpen;\n\t\t\t\t\tif ( self._modal ) {\n\t\t\t\t\t\tself._modal\n\t\t\t\t\t\t\t.addClass( self._modalOpenClasses )\n\t\t\t\t\t\t\t.height( Math.max( self._modal.height(), self.document.height() ) );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcomplete = function() {\n\n\t\t\t\t\t// Bail if the panel was closed before the opening animation has completed\n\t\t\t\t\tif ( !self._open ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._wrapper.addClass( o.classes.pageContentPrefix + \"-open\" );\n\t\t\t\t\t\tself._fixedToolbars().addClass( o.classes.pageContentPrefix + \"-open\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tself._bindFixListener();\n\n\t\t\t\t\tself._trigger( \"open\" );\n\n\t\t\t\t\tself._openedPage = self._page();\n\t\t\t\t};\n\n\t\t\tself._trigger( \"beforeopen\" );\n\n\t\t\tif ( self._page().jqmData( \"panel\" ) === \"open\" ) {\n\t\t\t\tself._on( self.document, {\n\t\t\t\t\t\"panelclose\": _openPanel\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t_openPanel();\n\t\t\t}\n\n\t\t\tself._open = true;\n\t\t}\n\t},\n\n\tclose: function( immediate ) {\n\t\tif ( this._open ) {\n\t\t\tvar self = this,\n\t\t\t\to = this.options,\n\n\t\t\t\t_closePanel = function() {\n\n\t\t\t\t\tself.element.removeClass( o.classes.panelOpen );\n\n\t\t\t\t\tif ( o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._wrapper.removeClass( self._pageContentOpenClasses );\n\t\t\t\t\t\tself._fixedToolbars().removeClass( self._pageContentOpenClasses );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !immediate && $.support.cssTransform3d && !!o.animate ) {\n\t\t\t\t\t\t( self._wrapper || self.element )\n\t\t\t\t\t\t\t.animationComplete( complete, \"transition\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetTimeout( complete, 0 );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( self._modal ) {\n\t\t\t\t\t\tself._modal\n\t\t\t\t\t\t\t.removeClass( self._modalOpenClasses )\n\t\t\t\t\t\t\t.height( \"\" );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcomplete = function() {\n\t\t\t\t\tif ( o.theme && o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._page().parent().removeClass( o.classes.pageContainer + \"-themed \" + o.classes.pageContainer + \"-\" + o.theme );\n\t\t\t\t\t}\n\n\t\t\t\t\tself.element.addClass( o.classes.panelClosed );\n\n\t\t\t\t\tif ( o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._page().parent().removeClass( o.classes.pageContainer );\n\t\t\t\t\t\tself._wrapper.removeClass( o.classes.pageContentPrefix + \"-open\" );\n\t\t\t\t\t\tself._fixedToolbars().removeClass( o.classes.pageContentPrefix + \"-open\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( $.support.cssTransform3d && !!o.animate && o.display !== \"overlay\" ) {\n\t\t\t\t\t\tself._wrapper.removeClass( o.classes.animate );\n\t\t\t\t\t\tself._fixedToolbars().removeClass( o.classes.animate );\n\t\t\t\t\t}\n\n\t\t\t\t\tself._fixPanel();\n\t\t\t\t\tself._unbindFixListener();\n\t\t\t\t\t$.mobile.resetActivePageHeight();\n\n\t\t\t\t\tself._page().jqmRemoveData( \"panel\" );\n\n\t\t\t\t\tself._trigger( \"close\" );\n\n\t\t\t\t\tself._openedPage = null;\n\t\t\t\t};\n\n\t\t\tself._trigger( \"beforeclose\" );\n\n\t\t\t_closePanel();\n\n\t\t\tself._open = false;\n\t\t}\n\t},\n\n\ttoggle: function() {\n\t\tthis[ this._open ? \"close\" : \"open\" ]();\n\t},\n\n\t_destroy: function() {\n\t\tvar otherPanels,\n\t\to = this.options,\n\t\tmultiplePanels = ( $( \"body > :mobile-panel\" ).length + $.mobile.activePage.find( \":mobile-panel\" ).length ) > 1;\n\n\t\tif ( o.display !== \"overlay\" ) {\n\n\t\t\t//  remove the wrapper if not in use by another panel\n\t\t\totherPanels = $( \"body > :mobile-panel\" ).add( $.mobile.activePage.find( \":mobile-panel\" ) );\n\t\t\tif ( otherPanels.not( \".ui-panel-display-overlay\" ).not( this.element ).length === 0 ) {\n\t\t\t\tthis._wrapper.children().unwrap();\n\t\t\t}\n\n\t\t\tif ( this._open ) {\n\n\t\t\t\tthis._fixedToolbars().removeClass( o.classes.pageContentPrefix + \"-open\" );\n\n\t\t\t\tif ( $.support.cssTransform3d && !!o.animate ) {\n\t\t\t\t\tthis._fixedToolbars().removeClass( o.classes.animate );\n\t\t\t\t}\n\n\t\t\t\tthis._page().parent().removeClass( o.classes.pageContainer );\n\n\t\t\t\tif ( o.theme ) {\n\t\t\t\t\tthis._page().parent().removeClass( o.classes.pageContainer + \"-themed \" + o.classes.pageContainer + \"-\" + o.theme );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( !multiplePanels ) {\n\n\t\t\tthis.document.off( \"panelopen panelclose\" );\n\n\t\t}\n\n\t\tif ( this._open ) {\n\t\t\tthis._page().jqmRemoveData( \"panel\" );\n\t\t}\n\n\t\tthis._panelInner.children().unwrap();\n\n\t\tthis.element\n\t\t\t.removeClass( [ this._getPanelClasses(), o.classes.panelOpen, o.classes.animate ].join( \" \" ) )\n\t\t\t.off( \"swipeleft.panel swiperight.panel\" )\n\t\t\t.off( \"panelbeforeopen\" )\n\t\t\t.off( \"panelhide\" )\n\t\t\t.off( \"keyup.panel\" )\n\t\t\t.off( \"updatelayout\" );\n\n\t\tif ( this._modal ) {\n\t\t\tthis._modal.remove();\n\t\t}\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.table\", {\n\toptions: {\n\t\tclasses: {\n\t\t\ttable: \"ui-table\"\n\t\t},\n\t\tenhanced: false\n\t},\n\n\t_create: function() {\n\t\tif ( !this.options.enhanced ) {\n\t\t\tthis.element.addClass( this.options.classes.table );\n\t\t}\n\n\t\t// extend here, assign on refresh > _setHeaders\n\t\t$.extend( this, {\n\n\t\t\t// Expose headers and allHeaders properties on the widget\n\t\t\t// headers references the THs within the first TR in the table\n\t\t\theaders: undefined,\n\n\t\t\t// allHeaders references headers, plus all THs in the thead, which may\n\t\t\t// include several rows, or not\n\t\t\tallHeaders: undefined\n\t\t});\n\n\t\tthis._refresh( true );\n\t},\n\n\t_setHeaders: function() {\n\t\tvar trs = this.element.find( \"thead tr\" );\n\n\t\tthis.headers = this.element.find( \"tr:eq(0)\" ).children();\n\t\tthis.allHeaders = this.headers.add( trs.children() );\n\t},\n\n\trefresh: function() {\n\t\tthis._refresh();\n\t},\n\n\trebuild: $.noop,\n\n\t_refresh: function( /* create */ ) {\n\t\tvar table = this.element,\n\t\t\ttrs = table.find( \"thead tr\" );\n\n\t\t// updating headers on refresh (fixes #5880)\n\t\tthis._setHeaders();\n\n\t\t// Iterate over the trs\n\t\ttrs.each( function() {\n\t\t\tvar columnCount = 0;\n\n\t\t\t// Iterate over the children of the tr\n\t\t\t$( this ).children().each( function() {\n\t\t\t\tvar span = parseInt( this.getAttribute( \"colspan\" ), 10 ),\n\t\t\t\t\tselector = \":nth-child(\" + ( columnCount + 1 ) + \")\",\n\t\t\t\t\tj;\n\n\t\t\t\tthis.setAttribute( \"data-\" + $.mobile.ns + \"colstart\", columnCount + 1 );\n\n\t\t\t\tif ( span ) {\n\t\t\t\t\tfor( j = 0; j < span - 1; j++ ) {\n\t\t\t\t\t\tcolumnCount++;\n\t\t\t\t\t\tselector += \", :nth-child(\" + ( columnCount + 1 ) + \")\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Store \"cells\" data on header as a reference to all cells in the\n\t\t\t\t// same column as this TH\n\t\t\t\t$( this ).jqmData( \"cells\", table.find( \"tr\" ).not( trs.eq( 0 ) ).not( this ).children( selector ) );\n\n\t\t\t\tcolumnCount++;\n\t\t\t});\n\t\t});\n\t}\n});\n\n})( jQuery );\n\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.table\", $.mobile.table, {\n\toptions: {\n\t\tmode: \"columntoggle\",\n\t\tcolumnBtnTheme: null,\n\t\tcolumnPopupTheme: null,\n\t\tcolumnBtnText: \"Columns...\",\n\t\tclasses: $.extend( $.mobile.table.prototype.options.classes, {\n\t\t\tpopup: \"ui-table-columntoggle-popup\",\n\t\t\tcolumnBtn: \"ui-table-columntoggle-btn\",\n\t\t\tpriorityPrefix: \"ui-table-priority-\",\n\t\t\tcolumnToggleTable: \"ui-table-columntoggle\"\n\t\t})\n\t},\n\n\t_create: function() {\n\t\tthis._super();\n\n\t\tif ( this.options.mode !== \"columntoggle\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$.extend( this, {\n\t\t\t_menu: null\n\t\t});\n\n\t\tif ( this.options.enhanced ) {\n\t\t\tthis._menu = $( this.document[ 0 ].getElementById( this._id() + \"-popup\" ) ).children().first();\n\t\t\tthis._addToggles( this._menu, true );\n\t\t} else {\n\t\t\tthis._menu = this._enhanceColToggle();\n\t\t\tthis.element.addClass( this.options.classes.columnToggleTable );\n\t\t}\n\n\t\tthis._setupEvents();\n\n\t\tthis._setToggleState();\n\t},\n\n\t_id: function() {\n\t\treturn ( this.element.attr( \"id\" ) || ( this.widgetName + this.uuid ) );\n\t},\n\n\t_setupEvents: function() {\n\t\t//NOTE: inputs are bound in bindToggles,\n\t\t// so it can be called on refresh, too\n\n\t\t// update column toggles on resize\n\t\tthis._on( this.window, {\n\t\t\tthrottledresize: \"_setToggleState\"\n\t\t});\n\t\tthis._on( this._menu, {\n\t\t\t\"change input\": \"_menuInputChange\"\n\t\t});\n\t},\n\n\t_addToggles: function( menu, keep ) {\n\t\tvar inputs,\n\t\t\tcheckboxIndex = 0,\n\t\t\topts = this.options,\n\t\t\tcontainer = menu.controlgroup( \"container\" );\n\n\t\t// allow update of menu on refresh (fixes #5880)\n\t\tif ( keep ) {\n\t\t\tinputs = menu.find( \"input\" );\n\t\t} else {\n\t\t\tcontainer.empty();\n\t\t}\n\n\t\t// create the hide/show toggles\n\t\tthis.headers.not( \"td\" ).each( function() {\n\t\t\tvar input, cells,\n\t\t\t\theader = $( this ),\n\t\t\t\tpriority = $.mobile.getAttribute( this, \"priority\" );\n\n\t\t\tif ( priority ) {\n\t\t\t\tcells = header.add( header.jqmData( \"cells\" ) );\n\t\t\t\tcells.addClass( opts.classes.priorityPrefix + priority );\n\n\t\t\t\t// Make sure the (new?) checkbox is associated with its header via .jqmData() and\n\t\t\t\t// that, vice versa, the header is also associated with the checkbox\n\t\t\t\tinput = ( keep ? inputs.eq( checkboxIndex++ ) :\n\t\t\t\t\t$(\"<label><input type='checkbox' checked />\" +\n\t\t\t\t\t\t( header.children( \"abbr\" ).first().attr( \"title\" ) ||\n\t\t\t\t\t\t\theader.text() ) +\n\t\t\t\t\t\t\"</label>\" )\n\t\t\t\t\t\t.appendTo( container )\n\t\t\t\t\t\t.children( 0 )\n\t\t\t\t\t\t.checkboxradio( {\n\t\t\t\t\t\t\ttheme: opts.columnPopupTheme\n\t\t\t\t\t\t}) )\n\n\t\t\t\t\t\t// Associate the header with the checkbox\n\t\t\t\t\t\t.jqmData( \"header\", header )\n\t\t\t\t\t\t.jqmData( \"cells\", cells );\n\n\t\t\t\t// Associate the checkbox with the header\n\t\t\t\theader.jqmData( \"input\", input );\n\t\t\t}\n\t\t});\n\n\t\t// set bindings here\n\t\tif ( !keep ) {\n\t\t\tmenu.controlgroup( \"refresh\" );\n\t\t}\n\t},\n\n\t_menuInputChange: function( evt ) {\n\t\tvar input = $( evt.target ),\n\t\t\tchecked = input[ 0 ].checked;\n\n\t\tinput.jqmData( \"cells\" )\n\t\t\t.toggleClass( \"ui-table-cell-hidden\", !checked )\n\t\t\t.toggleClass( \"ui-table-cell-visible\", checked );\n\t},\n\n\t_unlockCells: function( cells ) {\n\t\t// allow hide/show via CSS only = remove all toggle-locks\n\t\tcells.removeClass( \"ui-table-cell-hidden ui-table-cell-visible\");\n\t},\n\n\t_enhanceColToggle: function() {\n\t\tvar id , menuButton, popup, menu,\n\t\t\ttable = this.element,\n\t\t\topts = this.options,\n\t\t\tns = $.mobile.ns,\n\t\t\tfragment = this.document[ 0 ].createDocumentFragment();\n\n\t\tid = this._id() + \"-popup\";\n\t\tmenuButton = $( \"<a href='#\" + id + \"' \" +\n\t\t\t\"class='\" + opts.classes.columnBtn + \" ui-btn \" +\n\t\t\t\"ui-btn-\" + ( opts.columnBtnTheme || \"a\" ) +\n\t\t\t\" ui-corner-all ui-shadow ui-mini' \" +\n\t\t\t\"data-\" + ns + \"rel='popup'>\" + opts.columnBtnText + \"</a>\" );\n\t\tpopup = $( \"<div class='\" + opts.classes.popup + \"' id='\" + id + \"'></div>\" );\n\t\tmenu = $( \"<fieldset></fieldset>\" ).controlgroup();\n\n\t\t// set extension here, send \"false\" to trigger build/rebuild\n\t\tthis._addToggles( menu, false );\n\n\t\tmenu.appendTo( popup );\n\n\t\tfragment.appendChild( popup[ 0 ] );\n\t\tfragment.appendChild( menuButton[ 0 ] );\n\t\ttable.before( fragment );\n\n\t\tpopup.popup();\n\n\t\treturn menu;\n\t},\n\n\trebuild: function() {\n\t\tthis._super();\n\n\t\tif ( this.options.mode === \"columntoggle\" ) {\n\t\t\t// NOTE: rebuild passes \"false\", while refresh passes \"undefined\"\n\t\t\t// both refresh the table, but inside addToggles, !false will be true,\n\t\t\t// so a rebuild call can be indentified\n\t\t\tthis._refresh( false );\n\t\t}\n\t},\n\n\t_refresh: function( create ) {\n\t\tvar headers, hiddenColumns, index;\n\n\t\t// Calling _super() here updates this.headers\n\t\tthis._super( create );\n\n\t\tif ( !create && this.options.mode === \"columntoggle\" ) {\n\t\t\theaders = this.headers;\n\t\t\thiddenColumns = [];\n\n\t\t\t// Find the index of the column header associated with each old checkbox among the\n\t\t\t// post-refresh headers and, if the header is still there, make sure the corresponding\n\t\t\t// column will be hidden if the pre-refresh checkbox indicates that the column is\n\t\t\t// hidden by recording its index in the array of hidden columns.\n\t\t\tthis._menu.find( \"input\" ).each( function() {\n\t\t\t\tvar input = $( this ),\n\t\t\t\t\theader = input.jqmData( \"header\" ),\n\t\t\t\t\tindex = headers.index( header[ 0 ] );\n\n\t\t\t\tif ( index > -1 && !input.prop( \"checked\" ) ) {\n\n\t\t\t\t\t// The column header associated with /this/ checkbox is still present in the\n\t\t\t\t\t// post-refresh table and the checkbox is not checked, so the column associated\n\t\t\t\t\t// with this column header is currently hidden. Let's record that.\n\t\t\t\t\thiddenColumns.push( index );\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// columns not being replaced must be cleared from input toggle-locks\n\t\t\tthis._unlockCells( this.element.find( \".ui-table-cell-hidden, \" +\n\t\t\t\t\".ui-table-cell-visible\" ) );\n\n\t\t\t// update columntoggles and cells\n\t\t\tthis._addToggles( this._menu, create );\n\n\t\t\t// At this point all columns are visible, so uncheck the checkboxes that correspond to\n\t\t\t// those columns we've found to be hidden\n\t\t\tfor ( index = hiddenColumns.length - 1 ; index > -1 ; index-- ) {\n\t\t\t\theaders.eq( hiddenColumns[ index ] ).jqmData( \"input\" )\n\t\t\t\t\t.prop( \"checked\", false )\n\t\t\t\t\t.checkboxradio( \"refresh\" )\n\t\t\t\t\t.trigger( \"change\" );\n\t\t\t}\n\t\t}\n\t},\n\n\t_setToggleState: function() {\n\t\tthis._menu.find( \"input\" ).each( function() {\n\t\t\tvar checkbox = $( this );\n\n\t\t\tthis.checked = checkbox.jqmData( \"cells\" ).eq( 0 ).css( \"display\" ) === \"table-cell\";\n\t\t\tcheckbox.checkboxradio( \"refresh\" );\n\t\t});\n\t},\n\n\t_destroy: function() {\n\t\tthis._super();\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n$.widget( \"mobile.table\", $.mobile.table, {\n\toptions: {\n\t\tmode: \"reflow\",\n\t\tclasses: $.extend( $.mobile.table.prototype.options.classes, {\n\t\t\treflowTable: \"ui-table-reflow\",\n\t\t\tcellLabels: \"ui-table-cell-label\"\n\t\t})\n\t},\n\n\t_create: function() {\n\t\tthis._super();\n\n\t\t// If it's not reflow mode, return here.\n\t\tif ( this.options.mode !== \"reflow\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !this.options.enhanced ) {\n\t\t\tthis.element.addClass( this.options.classes.reflowTable );\n\n\t\t\tthis._updateReflow();\n\t\t}\n\t},\n\n\trebuild: function() {\n\t\tthis._super();\n\n\t\tif ( this.options.mode === \"reflow\" ) {\n\t\t\tthis._refresh( false );\n\t\t}\n\t},\n\n\t_refresh: function( create ) {\n\t\tthis._super( create );\n\t\tif ( !create && this.options.mode === \"reflow\" ) {\n\t\t\tthis._updateReflow( );\n\t\t}\n\t},\n\n\t_updateReflow: function() {\n\t\tvar table = this,\n\t\t\topts = this.options;\n\n\t\t// get headers in reverse order so that top-level headers are appended last\n\t\t$( table.allHeaders.get().reverse() ).each( function() {\n\t\t\tvar cells = $( this ).jqmData( \"cells\" ),\n\t\t\t\tcolstart = $.mobile.getAttribute( this, \"colstart\" ),\n\t\t\t\thierarchyClass = cells.not( this ).filter( \"thead th\" ).length && \" ui-table-cell-label-top\",\n\t\t\t\tcontents = $( this ).clone().contents(),\n\t\t\t\titeration, filter;\n\n\t\t\t\tif ( contents.length > 0  ) {\n\n\t\t\t\t\tif ( hierarchyClass ) {\n\t\t\t\t\t\titeration = parseInt( this.getAttribute( \"colspan\" ), 10 );\n\t\t\t\t\t\tfilter = \"\";\n\n\t\t\t\t\t\tif ( iteration ) {\n\t\t\t\t\t\t\tfilter = \"td:nth-child(\"+ iteration +\"n + \" + ( colstart ) +\")\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttable._addLabels( cells.filter( filter ),\n\t\t\t\t\t\t\topts.classes.cellLabels + hierarchyClass, contents );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttable._addLabels( cells, opts.classes.cellLabels, contents );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t});\n\t},\n\n\t_addLabels: function( cells, label, contents ) {\n\t\tif ( contents.length === 1 && contents[ 0 ].nodeName.toLowerCase() === \"abbr\" ) {\n\t\t\tcontents = contents.eq( 0 ).attr( \"title\" );\n\t\t}\n\t\t// .not fixes #6006\n\t\tcells\n\t\t\t.not( \":has(b.\" + label + \")\" )\n\t\t\t\t.prepend( $( \"<b class='\" + label + \"'></b>\" ).append( contents ) );\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n// TODO rename filterCallback/deprecate and default to the item itself as the first argument\nvar defaultFilterCallback = function( index, searchValue ) {\n\treturn ( ( \"\" + ( $.mobile.getAttribute( this, \"filtertext\" ) || $( this ).text() ) )\n\t\t.toLowerCase().indexOf( searchValue ) === -1 );\n};\n\n$.widget( \"mobile.filterable\", {\n\n\tinitSelector: \":jqmData(filter='true')\",\n\n\toptions: {\n\t\tfilterReveal: false,\n\t\tfilterCallback: defaultFilterCallback,\n\t\tenhanced: false,\n\t\tinput: null,\n\t\tchildren: \"> li, > option, > optgroup option, > tbody tr, > .ui-controlgroup-controls > .ui-btn, > .ui-controlgroup-controls > .ui-checkbox, > .ui-controlgroup-controls > .ui-radio\"\n\t},\n\n\t_create: function() {\n\t\tvar opts = this.options;\n\n\t\t$.extend( this, {\n\t\t\t_search: null,\n\t\t\t_timer: 0\n\t\t});\n\n\t\tthis._setInput( opts.input );\n\t\tif ( !opts.enhanced ) {\n\t\t\tthis._filterItems( ( ( this._search && this._search.val() ) || \"\" ).toLowerCase() );\n\t\t}\n\t},\n\n\t_onKeyUp: function() {\n\t\tvar val, lastval,\n\t\t\tsearch = this._search;\n\n\t\tif ( search ) {\n\t\t\tval = search.val().toLowerCase(),\n\t\t\tlastval = $.mobile.getAttribute( search[ 0 ], \"lastval\" ) + \"\";\n\n\t\t\tif ( lastval && lastval === val ) {\n\t\t\t\t// Execute the handler only once per value change\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this._timer ) {\n\t\t\t\twindow.clearTimeout( this._timer );\n\t\t\t\tthis._timer = 0;\n\t\t\t}\n\n\t\t\tthis._timer = this._delay( function() {\n\t\t\t\tif ( this._trigger( \"beforefilter\", null, { input: search } ) === false ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t// Change val as lastval for next execution\n\t\t\t\tsearch[ 0 ].setAttribute( \"data-\" + $.mobile.ns + \"lastval\", val );\n\n\t\t\t\tthis._filterItems( val );\n\t\t\t\tthis._timer = 0;\n\t\t\t}, 250 );\n\t\t}\n\t},\n\n\t_getFilterableItems: function() {\n\t\tvar elem = this.element,\n\t\t\tchildren = this.options.children,\n\t\t\titems = !children ? { length: 0 }:\n\t\t\t\t$.isFunction( children ) ? children():\n\t\t\t\tchildren.nodeName ? $( children ):\n\t\t\t\tchildren.jquery ? children:\n\t\t\t\tthis.element.find( children );\n\n\t\tif ( items.length === 0 ) {\n\t\t\titems = elem.children();\n\t\t}\n\n\t\treturn items;\n\t},\n\n\t_filterItems: function( val ) {\n\t\tvar idx, callback, length, dst,\n\t\t\tshow = [],\n\t\t\thide = [],\n\t\t\topts = this.options,\n\t\t\tfilterItems = this._getFilterableItems();\n\n\t\tif ( val != null ) {\n\t\t\tcallback = opts.filterCallback || defaultFilterCallback;\n\t\t\tlength = filterItems.length;\n\n\t\t\t// Partition the items into those to be hidden and those to be shown\n\t\t\tfor ( idx = 0 ; idx < length ; idx++ ) {\n\t\t\t\tdst = ( callback.call( filterItems[ idx ], idx, val ) ) ? hide : show;\n\t\t\t\tdst.push( filterItems[ idx ] );\n\t\t\t}\n\t\t}\n\n\t\t// If nothing is hidden, then the decision whether to hide or show the items\n\t\t// is based on the \"filterReveal\" option.\n\t\tif ( hide.length === 0 ) {\n\t\t\tfilterItems[ ( opts.filterReveal && val.length === 0 ) ?\n\t\t\t\t\"addClass\" : \"removeClass\" ]( \"ui-screen-hidden\" );\n\t\t} else {\n\t\t\t$( hide ).addClass( \"ui-screen-hidden\" );\n\t\t\t$( show ).removeClass( \"ui-screen-hidden\" );\n\t\t}\n\n\t\tthis._refreshChildWidget();\n\n\t\tthis._trigger( \"filter\", null, {\n\t\t\titems: filterItems\n\t\t});\n\t},\n\n\t// The Default implementation of _refreshChildWidget attempts to call\n\t// refresh on collapsibleset, controlgroup, selectmenu, or listview\n\t_refreshChildWidget: function() {\n\t\tvar widget, idx,\n\t\t\trecognizedWidgets = [ \"collapsibleset\", \"selectmenu\", \"controlgroup\", \"listview\" ];\n\n\t\tfor ( idx = recognizedWidgets.length - 1 ; idx > -1 ; idx-- ) {\n\t\t\twidget = recognizedWidgets[ idx ];\n\t\t\tif ( $.mobile[ widget ] ) {\n\t\t\t\twidget = this.element.data( \"mobile-\" + widget );\n\t\t\t\tif ( widget && $.isFunction( widget.refresh ) ) {\n\t\t\t\t\twidget.refresh();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// TODO: When the input is not internal, do not even store it in this._search\n\t_setInput: function ( selector ) {\n\t\tvar search = this._search;\n\n\t\t// Stop a pending filter operation\n\t\tif ( this._timer ) {\n\t\t\twindow.clearTimeout( this._timer );\n\t\t\tthis._timer = 0;\n\t\t}\n\n\t\tif ( search ) {\n\t\t\tthis._off( search, \"keyup change input\" );\n\t\t\tsearch = null;\n\t\t}\n\n\t\tif ( selector ) {\n\t\t\tsearch = selector.jquery ? selector:\n\t\t\t\tselector.nodeName ? $( selector ):\n\t\t\t\tthis.document.find( selector );\n\n\t\t\tthis._on( search, {\n\t\t\t\tkeydown: \"_onKeyDown\",\n\t\t\t\tkeypress: \"_onKeyPress\",\n\t\t\t\tkeyup: \"_onKeyUp\",\n\t\t\t\tchange: \"_onKeyUp\",\n\t\t\t\tinput: \"_onKeyUp\"\n\t\t\t});\n\t\t}\n\n\t\tthis._search = search;\n\t},\n\n\t// Prevent form submission\n\t_onKeyDown: function( event ) {\n\t\tif ( event.keyCode === $.ui.keyCode.ENTER ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._preventKeyPress = true;\n\t\t}\n\t},\n\n\t_onKeyPress: function( event ) {\n\t\tif ( this._preventKeyPress ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis._preventKeyPress = false;\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar refilter = !( ( options.filterReveal === undefined ) &&\n\t\t\t\t( options.filterCallback === undefined ) &&\n\t\t\t\t( options.children === undefined ) );\n\n\t\tthis._super( options );\n\n\t\tif ( options.input !== undefined ) {\n\t\t\tthis._setInput( options.input );\n\t\t\trefilter = true;\n\t\t}\n\n\t\tif ( refilter ) {\n\t\t\tthis.refresh();\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tvar opts = this.options,\n\t\t\titems = this._getFilterableItems();\n\n\t\tif ( opts.enhanced ) {\n\t\t\titems.toggleClass( \"ui-screen-hidden\", opts.filterReveal );\n\t\t} else {\n\t\t\titems.removeClass( \"ui-screen-hidden\" );\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tif ( this._timer ) {\n\t\t\twindow.clearTimeout( this._timer );\n\t\t\tthis._timer = 0;\n\t\t}\n\t\tthis._filterItems( ( ( this._search && this._search.val() ) || \"\" ).toLowerCase() );\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n// Create a function that will replace the _setOptions function of a widget,\n// and will pass the options on to the input of the filterable.\nvar replaceSetOptions = function( self, orig ) {\n\t\treturn function( options ) {\n\t\t\torig.call( this, options );\n\t\t\tself._syncTextInputOptions( options );\n\t\t};\n\t},\n\trDividerListItem = /(^|\\s)ui-li-divider(\\s|$)/,\n\torigDefaultFilterCallback = $.mobile.filterable.prototype.options.filterCallback;\n\n// Override the default filter callback with one that does not hide list dividers\n$.mobile.filterable.prototype.options.filterCallback = function( index, searchValue ) {\n\treturn !this.className.match( rDividerListItem ) &&\n\t\torigDefaultFilterCallback.call( this, index, searchValue );\n};\n\n$.widget( \"mobile.filterable\", $.mobile.filterable, {\n\toptions: {\n\t\tfilterPlaceholder: \"Filter items...\",\n\t\tfilterTheme: null\n\t},\n\n\t_create: function() {\n\t\tvar idx, widgetName,\n\t\t\telem = this.element,\n\t\t\trecognizedWidgets = [ \"collapsibleset\", \"selectmenu\", \"controlgroup\", \"listview\" ],\n\t\t\tcreateHandlers = {};\n\n\t\tthis._super();\n\n\t\t$.extend( this, {\n\t\t\t_widget: null\n\t\t});\n\n\t\tfor ( idx = recognizedWidgets.length - 1 ; idx > -1 ; idx-- ) {\n\t\t\twidgetName = recognizedWidgets[ idx ];\n\t\t\tif ( $.mobile[ widgetName ] ) {\n\t\t\t\tif ( this._setWidget( elem.data( \"mobile-\" + widgetName ) ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tcreateHandlers[ widgetName + \"create\" ] = \"_handleCreate\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( !this._widget ) {\n\t\t\tthis._on( elem, createHandlers );\n\t\t}\n\t},\n\n\t_handleCreate: function( evt ) {\n\t\tthis._setWidget( this.element.data( \"mobile-\" + evt.type.substring( 0, evt.type.length - 6 ) ) );\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tif ( this._widget && this._widget.widgetFullName === \"mobile-listview\" &&\n\t\t\ttype === \"beforefilter\" ) {\n\n\t\t\t// Also trigger listviewbeforefilter if this widget is also a listview\n\t\t\tthis._widget._trigger( \"beforefilter\", event, data );\n\t\t}\n\n\t\t// Passing back the response enables calling preventDefault()\n\t\treturn this._super( type, event, data );\n\t},\n\n\t_setWidget: function( widget ) {\n\t\tif ( !this._widget && widget ) {\n\t\t\tthis._widget = widget;\n\t\t\tthis._widget._setOptions = replaceSetOptions( this, this._widget._setOptions );\n\t\t}\n\n\t\tif ( !!this._widget ) {\n\t\t\tthis._syncTextInputOptions( this._widget.options );\n\t\t\tif ( this._widget.widgetName === \"listview\" ) {\n\t\t\t\tthis._widget.options.hideDividers = true;\n\t\t\t\tthis._widget.element.listview( \"refresh\" );\n\t\t\t}\n\t\t}\n\n\t\treturn !!this._widget;\n\t},\n\n\t_isSearchInternal: function() {\n\t\treturn ( this._search && this._search.jqmData( \"ui-filterable-\" + this.uuid + \"-internal\" ) );\n\t},\n\n\t_setInput: function( selector ) {\n\t\tvar opts = this.options,\n\t\t\tupdatePlaceholder = true,\n\t\t\ttextinputOpts = {};\n\n\t\tif ( !selector ) {\n\t\t\tif ( this._isSearchInternal() ) {\n\n\t\t\t\t// Ignore the call to set a new input if the selector goes to falsy and\n\t\t\t\t// the current textinput is already of the internally generated variety.\n\t\t\t\treturn;\n\t\t\t} else {\n\n\t\t\t\t// Generating a new textinput widget. No need to set the placeholder\n\t\t\t\t// further down the function.\n\t\t\t\tupdatePlaceholder = false;\n\t\t\t\tselector = $( \"<input \" +\n\t\t\t\t\t\"data-\" + $.mobile.ns + \"type='search' \" +\n\t\t\t\t\t\"placeholder='\" + opts.filterPlaceholder + \"'></input>\" )\n\t\t\t\t\t.jqmData( \"ui-filterable-\" + this.uuid + \"-internal\", true );\n\t\t\t\t$( \"<form class='ui-filterable'></form>\" )\n\t\t\t\t\t.append( selector )\n\t\t\t\t\t.submit( function( evt ) {\n\t\t\t\t\t\tevt.preventDefault();\n\t\t\t\t\t\tselector.blur();\n\t\t\t\t\t})\n\t\t\t\t\t.insertBefore( this.element );\n\t\t\t\tif ( $.mobile.textinput ) {\n\t\t\t\t\tif ( this.options.filterTheme != null ) {\n\t\t\t\t\t\ttextinputOpts[ \"theme\" ] = opts.filterTheme;\n\t\t\t\t\t}\n\n\t\t\t\t\tselector.textinput( textinputOpts );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._super( selector );\n\n\t\tif ( this._isSearchInternal() && updatePlaceholder ) {\n\t\t\tthis._search.attr( \"placeholder\", this.options.filterPlaceholder );\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar ret = this._super( options );\n\n\t\t// Need to set the filterPlaceholder after having established the search input\n\t\tif ( options.filterPlaceholder !== undefined ) {\n\t\t\tif ( this._isSearchInternal() ) {\n\t\t\t\tthis._search.attr( \"placeholder\", options.filterPlaceholder );\n\t\t\t}\n\t\t}\n\n\t\tif ( options.filterTheme !== undefined && this._search && $.mobile.textinput ) {\n\t\t\tthis._search.textinput( \"option\", \"theme\", options.filterTheme );\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// The listview implementation accompanying this filterable backcompat layer will call\n\t// filterable.refresh() after it's done refreshing the listview to make sure the filterable\n\t// filters out any new items added. However, when the listview refresh has been initiated by\n\t// the filterable itself, then such filtering has already taken place, and calling the\n\t// filterable's refresh() method will cause an infinite recursion. We stop this by setting a\n\t// flag that will cause the filterable's refresh() method to short-circuit.\n\t_refreshChildWidget: function() {\n\t\tthis._refreshingChildWidget = true;\n\t\tthis._superApply( arguments );\n\t\tthis._refreshingChildWidget = false;\n\t},\n\n\trefresh: function() {\n\t\tif ( !this._refreshingChildWidget ) {\n\t\t\tthis._superApply( arguments );\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tif ( this._isSearchInternal() ) {\n\t\t\tthis._search.remove();\n\t\t}\n\t\tthis._super();\n\t},\n\n\t_syncTextInputOptions: function( options ) {\n\t\tvar idx,\n\t\t\ttextinputOptions = {};\n\n\t\t// We only sync options if the filterable's textinput is of the internally\n\t\t// generated variety, rather than one specified by the user.\n\t\tif ( this._isSearchInternal() && $.mobile.textinput ) {\n\n\t\t\t// Apply only the options understood by textinput\n\t\t\tfor ( idx in $.mobile.textinput.prototype.options ) {\n\t\t\t\tif ( options[ idx ] !== undefined ) {\n\t\t\t\t\tif ( idx === \"theme\" && this.options.filterTheme != null ) {\n\t\t\t\t\t\ttextinputOptions[ idx ] = this.options.filterTheme;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttextinputOptions[ idx ] = options[ idx ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._search.textinput( \"option\", textinputOptions );\n\t\t}\n\t}\n});\n\n// Instantiate a filterable on a listview that has the data-filter=\"true\" attribute\n// This is not necessary for static content, because the auto-enhance takes care of instantiating\n// the filterable upon encountering data-filter=\"true\". However, because of 1.3.x it is expected\n// that a listview with data-filter=\"true\" will be filterable even if you just instantiate a\n// listview on it. The extension below ensures that this continues to happen in 1.4.x.\n$.widget( \"mobile.listview\", $.mobile.listview, {\n\toptions: {\n\t\tfilter: false\n\t},\n\t_create: function() {\n\t\tif ( this.options.filter === true &&\n\t\t\t\t!this.element.data( \"mobile-filterable\" ) ) {\n\t\t\tthis.element.filterable();\n\t\t}\n\t\treturn this._super();\n\t},\n\n\trefresh: function() {\n\t\tvar filterable;\n\n\t\tthis._superApply( arguments );\n\n\t\tif ( this.options.filter === true ) {\n\t\t\tfilterable = this.element.data( \"mobile-filterable\" );\n\n\t\t\tif ( filterable ) {\n\t\t\t\tfilterable.refresh();\n\t\t\t}\n\t\t}\n\t}\n});\n\n})( jQuery );\n\n/*!\n * jQuery UI Tabs fadf2b312a05040436451c64bbfaf4814bc62c56\n * http://jqueryui.com\n *\n * Copyright 2013 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/tabs/\n *\n * Depends:\n *\tjquery.ui.core.js\n *\tjquery.ui.widget.js\n */\n(function( $, undefined ) {\n\nvar tabId = 0,\n\trhash = /#.*$/;\n\nfunction getNextTabId() {\n\treturn ++tabId;\n}\n\nfunction isLocal( anchor ) {\n\treturn anchor.hash.length > 1 &&\n\t\tdecodeURIComponent( anchor.href.replace( rhash, \"\" ) ) ===\n\t\t\tdecodeURIComponent( location.href.replace( rhash, \"\" ) );\n}\n\n$.widget( \"ui.tabs\", {\n\tversion: \"fadf2b312a05040436451c64bbfaf4814bc62c56\",\n\tdelay: 300,\n\toptions: {\n\t\tactive: null,\n\t\tcollapsible: false,\n\t\tevent: \"click\",\n\t\theightStyle: \"content\",\n\t\thide: null,\n\t\tshow: null,\n\n\t\t// callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null,\n\t\tbeforeLoad: null,\n\t\tload: null\n\t},\n\n\t_create: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tthis.running = false;\n\n\t\tthis.element\n\t\t\t.addClass( \"ui-tabs ui-widget ui-widget-content ui-corner-all\" )\n\t\t\t.toggleClass( \"ui-tabs-collapsible\", options.collapsible )\n\t\t\t// Prevent users from focusing disabled tabs via click\n\t\t\t.delegate( \".ui-tabs-nav > li\", \"mousedown\" + this.eventNamespace, function( event ) {\n\t\t\t\tif ( $( this ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t})\n\t\t\t// support: IE <9\n\t\t\t// Preventing the default action in mousedown doesn't prevent IE\n\t\t\t// from focusing the element, so if the anchor gets focused, blur.\n\t\t\t// We don't have to worry about focusing the previously focused\n\t\t\t// element since clicking on a non-focusable element should focus\n\t\t\t// the body anyway.\n\t\t\t.delegate( \".ui-tabs-anchor\", \"focus\" + this.eventNamespace, function() {\n\t\t\t\tif ( $( this ).closest( \"li\" ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis._processTabs();\n\t\toptions.active = this._initialActive();\n\n\t\t// Take disabling tabs via class attribute from HTML\n\t\t// into account and update option properly.\n\t\tif ( $.isArray( options.disabled ) ) {\n\t\t\toptions.disabled = $.unique( options.disabled.concat(\n\t\t\t\t$.map( this.tabs.filter( \".ui-state-disabled\" ), function( li ) {\n\t\t\t\t\treturn that.tabs.index( li );\n\t\t\t\t})\n\t\t\t) ).sort();\n\t\t}\n\n\t\t// check for length avoids error when initializing empty list\n\t\tif ( this.options.active !== false && this.anchors.length ) {\n\t\t\tthis.active = this._findActive( options.active );\n\t\t} else {\n\t\t\tthis.active = $();\n\t\t}\n\n\t\tthis._refresh();\n\n\t\tif ( this.active.length ) {\n\t\t\tthis.load( options.active );\n\t\t}\n\t},\n\n\t_initialActive: function() {\n\t\tvar active = this.options.active,\n\t\t\tcollapsible = this.options.collapsible,\n\t\t\tlocationHash = location.hash.substring( 1 );\n\n\t\tif ( active === null ) {\n\t\t\t// check the fragment identifier in the URL\n\t\t\tif ( locationHash ) {\n\t\t\t\tthis.tabs.each(function( i, tab ) {\n\t\t\t\t\tif ( $( tab ).attr( \"aria-controls\" ) === locationHash ) {\n\t\t\t\t\t\tactive = i;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// check for a tab marked active via a class\n\t\t\tif ( active === null ) {\n\t\t\t\tactive = this.tabs.index( this.tabs.filter( \".ui-tabs-active\" ) );\n\t\t\t}\n\n\t\t\t// no active tab, set to false\n\t\t\tif ( active === null || active === -1 ) {\n\t\t\t\tactive = this.tabs.length ? 0 : false;\n\t\t\t}\n\t\t}\n\n\t\t// handle numbers: negative, out of range\n\t\tif ( active !== false ) {\n\t\t\tactive = this.tabs.index( this.tabs.eq( active ) );\n\t\t\tif ( active === -1 ) {\n\t\t\t\tactive = collapsible ? false : 0;\n\t\t\t}\n\t\t}\n\n\t\t// don't allow collapsible: false and active: false\n\t\tif ( !collapsible && active === false && this.anchors.length ) {\n\t\t\tactive = 0;\n\t\t}\n\n\t\treturn active;\n\t},\n\n\t_getCreateEventData: function() {\n\t\treturn {\n\t\t\ttab: this.active,\n\t\t\tpanel: !this.active.length ? $() : this._getPanelForTab( this.active )\n\t\t};\n\t},\n\n\t_tabKeydown: function( event ) {\n\t\tvar focusedTab = $( this.document[0].activeElement ).closest( \"li\" ),\n\t\t\tselectedIndex = this.tabs.index( focusedTab ),\n\t\t\tgoingForward = true;\n\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( event.keyCode ) {\n\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tselectedIndex++;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.UP:\n\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\tgoingForward = false;\n\t\t\t\tselectedIndex--;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.END:\n\t\t\t\tselectedIndex = this.anchors.length - 1;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\tselectedIndex = 0;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.SPACE:\n\t\t\t\t// Activate only, no collapsing\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclearTimeout( this.activating );\n\t\t\t\tthis._activate( selectedIndex );\n\t\t\t\treturn;\n\t\t\tcase $.ui.keyCode.ENTER:\n\t\t\t\t// Toggle (cancel delayed activation, allow collapsing)\n\t\t\t\tevent.preventDefault();\n\t\t\t\tclearTimeout( this.activating );\n\t\t\t\t// Determine if we should collapse or activate\n\t\t\t\tthis._activate( selectedIndex === this.options.active ? false : selectedIndex );\n\t\t\t\treturn;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\t// Focus the appropriate tab, based on which key was pressed\n\t\tevent.preventDefault();\n\t\tclearTimeout( this.activating );\n\t\tselectedIndex = this._focusNextTab( selectedIndex, goingForward );\n\n\t\t// Navigating with control key will prevent automatic activation\n\t\tif ( !event.ctrlKey ) {\n\t\t\t// Update aria-selected immediately so that AT think the tab is already selected.\n\t\t\t// Otherwise AT may confuse the user by stating that they need to activate the tab,\n\t\t\t// but the tab will already be activated by the time the announcement finishes.\n\t\t\tfocusedTab.attr( \"aria-selected\", \"false\" );\n\t\t\tthis.tabs.eq( selectedIndex ).attr( \"aria-selected\", \"true\" );\n\n\t\t\tthis.activating = this._delay(function() {\n\t\t\t\tthis.option( \"active\", selectedIndex );\n\t\t\t}, this.delay );\n\t\t}\n\t},\n\n\t_panelKeydown: function( event ) {\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+up moves focus to the current tab\n\t\tif ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.active.focus();\n\t\t}\n\t},\n\n\t// Alt+page up/down moves focus to the previous/next tab (and activates)\n\t_handlePageNav: function( event ) {\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active - 1, false ) );\n\t\t\treturn true;\n\t\t}\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active + 1, true ) );\n\t\t\treturn true;\n\t\t}\n\t},\n\n\t_findNextTab: function( index, goingForward ) {\n\t\tvar lastTabIndex = this.tabs.length - 1;\n\n\t\tfunction constrain() {\n\t\t\tif ( index > lastTabIndex ) {\n\t\t\t\tindex = 0;\n\t\t\t}\n\t\t\tif ( index < 0 ) {\n\t\t\t\tindex = lastTabIndex;\n\t\t\t}\n\t\t\treturn index;\n\t\t}\n\n\t\twhile ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {\n\t\t\tindex = goingForward ? index + 1 : index - 1;\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_focusNextTab: function( index, goingForward ) {\n\t\tindex = this._findNextTab( index, goingForward );\n\t\tthis.tabs.eq( index ).focus();\n\t\treturn index;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"active\" ) {\n\t\t\t// _activate() will handle invalid values and update this.options\n\t\t\tthis._activate( value );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\t// don't use the widget factory's disabled handling\n\t\t\tthis._setupDisabled( value );\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value);\n\n\t\tif ( key === \"collapsible\" ) {\n\t\t\tthis.element.toggleClass( \"ui-tabs-collapsible\", value );\n\t\t\t// Setting collapsible: false while collapsed; open first panel\n\t\t\tif ( !value && this.options.active === false ) {\n\t\t\t\tthis._activate( 0 );\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"event\" ) {\n\t\t\tthis._setupEvents( value );\n\t\t}\n\n\t\tif ( key === \"heightStyle\" ) {\n\t\t\tthis._setupHeightStyle( value );\n\t\t}\n\t},\n\n\t_tabId: function( tab ) {\n\t\treturn tab.attr( \"aria-controls\" ) || \"ui-tabs-\" + getNextTabId();\n\t},\n\n\t_sanitizeSelector: function( hash ) {\n\t\treturn hash ? hash.replace( /[!\"$%&'()*+,.\\/:;<=>?@\\[\\]\\^`{|}~]/g, \"\\\\$&\" ) : \"\";\n\t},\n\n\trefresh: function() {\n\t\tvar options = this.options,\n\t\t\tlis = this.tablist.children( \":has(a[href])\" );\n\n\t\t// get disabled tabs from class attribute from HTML\n\t\t// this will get converted to a boolean if needed in _refresh()\n\t\toptions.disabled = $.map( lis.filter( \".ui-state-disabled\" ), function( tab ) {\n\t\t\treturn lis.index( tab );\n\t\t});\n\n\t\tthis._processTabs();\n\n\t\t// was collapsed or no tabs\n\t\tif ( options.active === false || !this.anchors.length ) {\n\t\t\toptions.active = false;\n\t\t\tthis.active = $();\n\t\t// was active, but active tab is gone\n\t\t} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {\n\t\t\t// all remaining tabs are disabled\n\t\t\tif ( this.tabs.length === options.disabled.length ) {\n\t\t\t\toptions.active = false;\n\t\t\t\tthis.active = $();\n\t\t\t// activate previous tab\n\t\t\t} else {\n\t\t\t\tthis._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );\n\t\t\t}\n\t\t// was active, active tab still exists\n\t\t} else {\n\t\t\t// make sure active index is correct\n\t\t\toptions.active = this.tabs.index( this.active );\n\t\t}\n\n\t\tthis._refresh();\n\t},\n\n\t_refresh: function() {\n\t\tthis._setupDisabled( this.options.disabled );\n\t\tthis._setupEvents( this.options.event );\n\t\tthis._setupHeightStyle( this.options.heightStyle );\n\n\t\tthis.tabs.not( this.active ).attr({\n\t\t\t\"aria-selected\": \"false\",\n\t\t\ttabIndex: -1\n\t\t});\n\t\tthis.panels.not( this._getPanelForTab( this.active ) )\n\t\t\t.hide()\n\t\t\t.attr({\n\t\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t});\n\n\t\t// Make sure one tab is in the tab order\n\t\tif ( !this.active.length ) {\n\t\t\tthis.tabs.eq( 0 ).attr( \"tabIndex\", 0 );\n\t\t} else {\n\t\t\tthis.active\n\t\t\t\t.addClass( \"ui-tabs-active ui-state-active\" )\n\t\t\t\t.attr({\n\t\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\ttabIndex: 0\n\t\t\t\t});\n\t\t\tthis._getPanelForTab( this.active )\n\t\t\t\t.show()\n\t\t\t\t.attr({\n\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t});\n\t\t}\n\t},\n\n\t_processTabs: function() {\n\t\tvar that = this;\n\n\t\tthis.tablist = this._getList()\n\t\t\t.addClass( \"ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all\" )\n\t\t\t.attr( \"role\", \"tablist\" );\n\n\t\tthis.tabs = this.tablist.find( \"> li:has(a[href])\" )\n\t\t\t.addClass( \"ui-state-default ui-corner-top\" )\n\t\t\t.attr({\n\t\t\t\trole: \"tab\",\n\t\t\t\ttabIndex: -1\n\t\t\t});\n\n\t\tthis.anchors = this.tabs.map(function() {\n\t\t\t\treturn $( \"a\", this )[ 0 ];\n\t\t\t})\n\t\t\t.addClass( \"ui-tabs-anchor\" )\n\t\t\t.attr({\n\t\t\t\trole: \"presentation\",\n\t\t\t\ttabIndex: -1\n\t\t\t});\n\n\t\tthis.panels = $();\n\n\t\tthis.anchors.each(function( i, anchor ) {\n\t\t\tvar selector, panel, panelId,\n\t\t\t\tanchorId = $( anchor ).uniqueId().attr( \"id\" ),\n\t\t\t\ttab = $( anchor ).closest( \"li\" ),\n\t\t\t\toriginalAriaControls = tab.attr( \"aria-controls\" );\n\n\t\t\t// inline tab\n\t\t\tif ( isLocal( anchor ) ) {\n\t\t\t\tselector = anchor.hash;\n\t\t\t\tpanel = that.element.find( that._sanitizeSelector( selector ) );\n\t\t\t// remote tab\n\t\t\t} else {\n\t\t\t\tpanelId = that._tabId( tab );\n\t\t\t\tselector = \"#\" + panelId;\n\t\t\t\tpanel = that.element.find( selector );\n\t\t\t\tif ( !panel.length ) {\n\t\t\t\t\tpanel = that._createPanel( panelId );\n\t\t\t\t\tpanel.insertAfter( that.panels[ i - 1 ] || that.tablist );\n\t\t\t\t}\n\t\t\t\tpanel.attr( \"aria-live\", \"polite\" );\n\t\t\t}\n\n\t\t\tif ( panel.length) {\n\t\t\t\tthat.panels = that.panels.add( panel );\n\t\t\t}\n\t\t\tif ( originalAriaControls ) {\n\t\t\t\ttab.data( \"ui-tabs-aria-controls\", originalAriaControls );\n\t\t\t}\n\t\t\ttab.attr({\n\t\t\t\t\"aria-controls\": selector.substring( 1 ),\n\t\t\t\t\"aria-labelledby\": anchorId\n\t\t\t});\n\t\t\tpanel.attr( \"aria-labelledby\", anchorId );\n\t\t});\n\n\t\tthis.panels\n\t\t\t.addClass( \"ui-tabs-panel ui-widget-content ui-corner-bottom\" )\n\t\t\t.attr( \"role\", \"tabpanel\" );\n\t},\n\n\t// allow overriding how to find the list for rare usage scenarios (#7715)\n\t_getList: function() {\n\t\treturn this.element.find( \"ol,ul\" ).eq( 0 );\n\t},\n\n\t_createPanel: function( id ) {\n\t\treturn $( \"<div>\" )\n\t\t\t.attr( \"id\", id )\n\t\t\t.addClass( \"ui-tabs-panel ui-widget-content ui-corner-bottom\" )\n\t\t\t.data( \"ui-tabs-destroy\", true );\n\t},\n\n\t_setupDisabled: function( disabled ) {\n\t\tif ( $.isArray( disabled ) ) {\n\t\t\tif ( !disabled.length ) {\n\t\t\t\tdisabled = false;\n\t\t\t} else if ( disabled.length === this.anchors.length ) {\n\t\t\t\tdisabled = true;\n\t\t\t}\n\t\t}\n\n\t\t// disable tabs\n\t\tfor ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {\n\t\t\tif ( disabled === true || $.inArray( i, disabled ) !== -1 ) {\n\t\t\t\t$( li )\n\t\t\t\t\t.addClass( \"ui-state-disabled\" )\n\t\t\t\t\t.attr( \"aria-disabled\", \"true\" );\n\t\t\t} else {\n\t\t\t\t$( li )\n\t\t\t\t\t.removeClass( \"ui-state-disabled\" )\n\t\t\t\t\t.removeAttr( \"aria-disabled\" );\n\t\t\t}\n\t\t}\n\n\t\tthis.options.disabled = disabled;\n\t},\n\n\t_setupEvents: function( event ) {\n\t\tvar events = {\n\t\t\tclick: function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t};\n\t\tif ( event ) {\n\t\t\t$.each( event.split(\" \"), function( index, eventName ) {\n\t\t\t\tevents[ eventName ] = \"_eventHandler\";\n\t\t\t});\n\t\t}\n\n\t\tthis._off( this.anchors.add( this.tabs ).add( this.panels ) );\n\t\tthis._on( this.anchors, events );\n\t\tthis._on( this.tabs, { keydown: \"_tabKeydown\" } );\n\t\tthis._on( this.panels, { keydown: \"_panelKeydown\" } );\n\n\t\tthis._focusable( this.tabs );\n\t\tthis._hoverable( this.tabs );\n\t},\n\n\t_setupHeightStyle: function( heightStyle ) {\n\t\tvar maxHeight,\n\t\t\tparent = this.element.parent();\n\n\t\tif ( heightStyle === \"fill\" ) {\n\t\t\tmaxHeight = parent.height();\n\t\t\tmaxHeight -= this.element.outerHeight() - this.element.height();\n\n\t\t\tthis.element.siblings( \":visible\" ).each(function() {\n\t\t\t\tvar elem = $( this ),\n\t\t\t\t\tposition = elem.css( \"position\" );\n\n\t\t\t\tif ( position === \"absolute\" || position === \"fixed\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmaxHeight -= elem.outerHeight( true );\n\t\t\t});\n\n\t\t\tthis.element.children().not( this.panels ).each(function() {\n\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n\t\t\t});\n\n\t\t\tthis.panels.each(function() {\n\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n\t\t\t})\n\t\t\t.css( \"overflow\", \"auto\" );\n\t\t} else if ( heightStyle === \"auto\" ) {\n\t\t\tmaxHeight = 0;\n\t\t\tthis.panels.each(function() {\n\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).height( \"\" ).height() );\n\t\t\t}).height( maxHeight );\n\t\t}\n\t},\n\n\t_eventHandler: function( event ) {\n\t\tvar options = this.options,\n\t\t\tactive = this.active,\n\t\t\tanchor = $( event.currentTarget ),\n\t\t\ttab = anchor.closest( \"li\" ),\n\t\t\tclickedIsActive = tab[ 0 ] === active[ 0 ],\n\t\t\tcollapsing = clickedIsActive && options.collapsible,\n\t\t\ttoShow = collapsing ? $() : this._getPanelForTab( tab ),\n\t\t\ttoHide = !active.length ? $() : this._getPanelForTab( active ),\n\t\t\teventData = {\n\t\t\t\toldTab: active,\n\t\t\t\toldPanel: toHide,\n\t\t\t\tnewTab: collapsing ? $() : tab,\n\t\t\t\tnewPanel: toShow\n\t\t\t};\n\n\t\tevent.preventDefault();\n\n\t\tif ( tab.hasClass( \"ui-state-disabled\" ) ||\n\t\t\t\t// tab is already loading\n\t\t\t\ttab.hasClass( \"ui-tabs-loading\" ) ||\n\t\t\t\t// can't switch durning an animation\n\t\t\t\tthis.running ||\n\t\t\t\t// click on active header, but not collapsible\n\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n\t\t\t\t// allow canceling activation\n\t\t\t\t( this._trigger( \"beforeActivate\", event, eventData ) === false ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\toptions.active = collapsing ? false : this.tabs.index( tab );\n\n\t\tthis.active = clickedIsActive ? $() : tab;\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tif ( !toHide.length && !toShow.length ) {\n\t\t\t$.error( \"jQuery UI Tabs: Mismatching fragment identifier.\" );\n\t\t}\n\n\t\tif ( toShow.length ) {\n\t\t\tthis.load( this.tabs.index( tab ), event );\n\t\t}\n\t\tthis._toggle( event, eventData );\n\t},\n\n\t// handles show/hide for selecting tabs\n\t_toggle: function( event, eventData ) {\n\t\tvar that = this,\n\t\t\ttoShow = eventData.newPanel,\n\t\t\ttoHide = eventData.oldPanel;\n\n\t\tthis.running = true;\n\n\t\tfunction complete() {\n\t\t\tthat.running = false;\n\t\t\tthat._trigger( \"activate\", event, eventData );\n\t\t}\n\n\t\tfunction show() {\n\t\t\teventData.newTab.closest( \"li\" ).addClass( \"ui-tabs-active ui-state-active\" );\n\n\t\t\tif ( toShow.length && that.options.show ) {\n\t\t\t\tthat._show( toShow, that.options.show, complete );\n\t\t\t} else {\n\t\t\t\ttoShow.show();\n\t\t\t\tcomplete();\n\t\t\t}\n\t\t}\n\n\t\t// start out by hiding, then showing, then completing\n\t\tif ( toHide.length && this.options.hide ) {\n\t\t\tthis._hide( toHide, this.options.hide, function() {\n\t\t\t\teventData.oldTab.closest( \"li\" ).removeClass( \"ui-tabs-active ui-state-active\" );\n\t\t\t\tshow();\n\t\t\t});\n\t\t} else {\n\t\t\teventData.oldTab.closest( \"li\" ).removeClass( \"ui-tabs-active ui-state-active\" );\n\t\t\ttoHide.hide();\n\t\t\tshow();\n\t\t}\n\n\t\ttoHide.attr({\n\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\"aria-hidden\": \"true\"\n\t\t});\n\t\teventData.oldTab.attr( \"aria-selected\", \"false\" );\n\t\t// If we're switching tabs, remove the old tab from the tab order.\n\t\t// If we're opening from collapsed state, remove the previous tab from the tab order.\n\t\t// If we're collapsing, then keep the collapsing tab in the tab order.\n\t\tif ( toShow.length && toHide.length ) {\n\t\t\teventData.oldTab.attr( \"tabIndex\", -1 );\n\t\t} else if ( toShow.length ) {\n\t\t\tthis.tabs.filter(function() {\n\t\t\t\treturn $( this ).attr( \"tabIndex\" ) === 0;\n\t\t\t})\n\t\t\t.attr( \"tabIndex\", -1 );\n\t\t}\n\n\t\ttoShow.attr({\n\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\"aria-hidden\": \"false\"\n\t\t});\n\t\teventData.newTab.attr({\n\t\t\t\"aria-selected\": \"true\",\n\t\t\ttabIndex: 0\n\t\t});\n\t},\n\n\t_activate: function( index ) {\n\t\tvar anchor,\n\t\t\tactive = this._findActive( index );\n\n\t\t// trying to activate the already active panel\n\t\tif ( active[ 0 ] === this.active[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// trying to collapse, simulate a click on the current active header\n\t\tif ( !active.length ) {\n\t\t\tactive = this.active;\n\t\t}\n\n\t\tanchor = active.find( \".ui-tabs-anchor\" )[ 0 ];\n\t\tthis._eventHandler({\n\t\t\ttarget: anchor,\n\t\t\tcurrentTarget: anchor,\n\t\t\tpreventDefault: $.noop\n\t\t});\n\t},\n\n\t_findActive: function( index ) {\n\t\treturn index === false ? $() : this.tabs.eq( index );\n\t},\n\n\t_getIndex: function( index ) {\n\t\t// meta-function to give users option to provide a href string instead of a numerical index.\n\t\tif ( typeof index === \"string\" ) {\n\t\t\tindex = this.anchors.index( this.anchors.filter( \"[href$='\" + index + \"']\" ) );\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_destroy: function() {\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tthis.element.removeClass( \"ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible\" );\n\n\t\tthis.tablist\n\t\t\t.removeClass( \"ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all\" )\n\t\t\t.removeAttr( \"role\" );\n\n\t\tthis.anchors\n\t\t\t.removeClass( \"ui-tabs-anchor\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.removeAttr( \"tabIndex\" )\n\t\t\t.removeUniqueId();\n\n\t\tthis.tabs.add( this.panels ).each(function() {\n\t\t\tif ( $.data( this, \"ui-tabs-destroy\" ) ) {\n\t\t\t\t$( this ).remove();\n\t\t\t} else {\n\t\t\t\t$( this )\n\t\t\t\t\t.removeClass( \"ui-state-default ui-state-active ui-state-disabled \" +\n\t\t\t\t\t\t\"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel\" )\n\t\t\t\t\t.removeAttr( \"tabIndex\" )\n\t\t\t\t\t.removeAttr( \"aria-live\" )\n\t\t\t\t\t.removeAttr( \"aria-busy\" )\n\t\t\t\t\t.removeAttr( \"aria-selected\" )\n\t\t\t\t\t.removeAttr( \"aria-labelledby\" )\n\t\t\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t\t\t.removeAttr( \"aria-expanded\" )\n\t\t\t\t\t.removeAttr( \"role\" );\n\t\t\t}\n\t\t});\n\n\t\tthis.tabs.each(function() {\n\t\t\tvar li = $( this ),\n\t\t\t\tprev = li.data( \"ui-tabs-aria-controls\" );\n\t\t\tif ( prev ) {\n\t\t\t\tli\n\t\t\t\t\t.attr( \"aria-controls\", prev )\n\t\t\t\t\t.removeData( \"ui-tabs-aria-controls\" );\n\t\t\t} else {\n\t\t\t\tli.removeAttr( \"aria-controls\" );\n\t\t\t}\n\t\t});\n\n\t\tthis.panels.show();\n\n\t\tif ( this.options.heightStyle !== \"content\" ) {\n\t\t\tthis.panels.css( \"height\", \"\" );\n\t\t}\n\t},\n\n\tenable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = false;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.map( disabled, function( num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tdisabled = $.map( this.tabs, function( li, num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis._setupDisabled( disabled );\n\t},\n\n\tdisable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === true ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = true;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.inArray( index, disabled ) !== -1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.merge( [ index ], disabled ).sort();\n\t\t\t} else {\n\t\t\t\tdisabled = [ index ];\n\t\t\t}\n\t\t}\n\t\tthis._setupDisabled( disabled );\n\t},\n\n\tload: function( index, event ) {\n\t\tindex = this._getIndex( index );\n\t\tvar that = this,\n\t\t\ttab = this.tabs.eq( index ),\n\t\t\tanchor = tab.find( \".ui-tabs-anchor\" ),\n\t\t\tpanel = this._getPanelForTab( tab ),\n\t\t\teventData = {\n\t\t\t\ttab: tab,\n\t\t\t\tpanel: panel\n\t\t\t};\n\n\t\t// not remote\n\t\tif ( isLocal( anchor[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );\n\n\t\t// support: jQuery <1.8\n\t\t// jQuery <1.8 returns false if the request is canceled in beforeSend,\n\t\t// but as of 1.8, $.ajax() always returns a jqXHR object.\n\t\tif ( this.xhr && this.xhr.statusText !== \"canceled\" ) {\n\t\t\ttab.addClass( \"ui-tabs-loading\" );\n\t\t\tpanel.attr( \"aria-busy\", \"true\" );\n\n\t\t\tthis.xhr\n\t\t\t\t.success(function( response ) {\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tpanel.html( response );\n\t\t\t\t\t\tthat._trigger( \"load\", event, eventData );\n\t\t\t\t\t}, 1 );\n\t\t\t\t})\n\t\t\t\t.complete(function( jqXHR, status ) {\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tif ( status === \"abort\" ) {\n\t\t\t\t\t\t\tthat.panels.stop( false, true );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttab.removeClass( \"ui-tabs-loading\" );\n\t\t\t\t\t\tpanel.removeAttr( \"aria-busy\" );\n\n\t\t\t\t\t\tif ( jqXHR === that.xhr ) {\n\t\t\t\t\t\t\tdelete that.xhr;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 1 );\n\t\t\t\t});\n\t\t}\n\t},\n\n\t_ajaxSettings: function( anchor, event, eventData ) {\n\t\tvar that = this;\n\t\treturn {\n\t\t\turl: anchor.attr( \"href\" ),\n\t\t\tbeforeSend: function( jqXHR, settings ) {\n\t\t\t\treturn that._trigger( \"beforeLoad\", event,\n\t\t\t\t\t$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );\n\t\t\t}\n\t\t};\n\t},\n\n\t_getPanelForTab: function( tab ) {\n\t\tvar id = $( tab ).attr( \"aria-controls\" );\n\t\treturn this.element.find( this._sanitizeSelector( \"#\" + id ) );\n\t}\n});\n\n})( jQuery );\n\n(function( $, undefined ) {\n\n})( jQuery );\n\n(function( $, window ) {\n\n\t$.mobile.iosorientationfixEnabled = true;\n\n\t// This fix addresses an iOS bug, so return early if the UA claims it's something else.\n\tvar ua = navigator.userAgent,\n\t\tzoom,\n\t\tevt, x, y, z, aig;\n\tif ( !( /iPhone|iPad|iPod/.test( navigator.platform ) && /OS [1-5]_[0-9_]* like Mac OS X/i.test( ua ) && ua.indexOf( \"AppleWebKit\" ) > -1 ) ) {\n\t\t$.mobile.iosorientationfixEnabled = false;\n\t\treturn;\n\t}\n\n\tzoom = $.mobile.zoom;\n\n\tfunction checkTilt( e ) {\n\t\tevt = e.originalEvent;\n\t\taig = evt.accelerationIncludingGravity;\n\n\t\tx = Math.abs( aig.x );\n\t\ty = Math.abs( aig.y );\n\t\tz = Math.abs( aig.z );\n\n\t\t// If portrait orientation and in one of the danger zones\n\t\tif ( !window.orientation && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) ) {\n\t\t\t\tif ( zoom.enabled ) {\n\t\t\t\t\tzoom.disable();\n\t\t\t\t}\n\t\t}\telse if ( !zoom.enabled ) {\n\t\t\t\tzoom.enable();\n\t\t}\n\t}\n\n\t$.mobile.document.on( \"mobileinit\", function() {\n\t\tif ( $.mobile.iosorientationfixEnabled ) {\n\t\t\t$.mobile.window\n\t\t\t\t.bind( \"orientationchange.iosorientationfix\", zoom.enable )\n\t\t\t\t.bind( \"devicemotion.iosorientationfix\", checkTilt );\n\t\t}\n\t});\n\n}( jQuery, this ));\n\n(function( $, window, undefined ) {\n\tvar\t$html = $( \"html\" ),\n\t\t$window = $.mobile.window;\n\n\t//remove initial build class (only present on first pageshow)\n\tfunction hideRenderingClass() {\n\t\t$html.removeClass( \"ui-mobile-rendering\" );\n\t}\n\n\t// trigger mobileinit event - useful hook for configuring $.mobile settings before they're used\n\t$( window.document ).trigger( \"mobileinit\" );\n\n\t// support conditions\n\t// if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,\n\t// otherwise, proceed with the enhancements\n\tif ( !$.mobile.gradeA() ) {\n\t\treturn;\n\t}\n\n\t// override ajaxEnabled on platforms that have known conflicts with hash history updates\n\t// or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)\n\tif ( $.mobile.ajaxBlacklist ) {\n\t\t$.mobile.ajaxEnabled = false;\n\t}\n\n\t// Add mobile, initial load \"rendering\" classes to docEl\n\t$html.addClass( \"ui-mobile ui-mobile-rendering\" );\n\n\t// This is a fallback. If anything goes wrong (JS errors, etc), or events don't fire,\n\t// this ensures the rendering class is removed after 5 seconds, so content is visible and accessible\n\tsetTimeout( hideRenderingClass, 5000 );\n\n\t$.extend( $.mobile, {\n\t\t// find and enhance the pages in the dom and transition to the first page.\n\t\tinitializePage: function() {\n\t\t\t// find present pages\n\t\t\tvar path = $.mobile.path,\n\t\t\t\t$pages = $( \":jqmData(role='page'), :jqmData(role='dialog')\" ),\n\t\t\t\thash = path.stripHash( path.stripQueryParams(path.parseLocation().hash) ),\n\t\t\t\ttheLocation = $.mobile.path.parseLocation(),\n\t\t\t\thashPage = hash ? document.getElementById( hash ) : undefined;\n\n\t\t\t// if no pages are found, create one with body's inner html\n\t\t\tif ( !$pages.length ) {\n\t\t\t\t$pages = $( \"body\" ).wrapInner( \"<div data-\" + $.mobile.ns + \"role='page'></div>\" ).children( 0 );\n\t\t\t}\n\n\t\t\t// add dialogs, set data-url attrs\n\t\t\t$pages.each(function() {\n\t\t\t\tvar $this = $( this );\n\n\t\t\t\t// unless the data url is already set set it to the pathname\n\t\t\t\tif ( !$this[ 0 ].getAttribute( \"data-\" + $.mobile.ns + \"url\" ) ) {\n\t\t\t\t\t$this.attr( \"data-\" + $.mobile.ns + \"url\", $this.attr( \"id\" ) ||\n\t\t\t\t\t\tpath.convertUrlToDataUrl( theLocation.pathname + theLocation.search ) );\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)\n\t\t\t$.mobile.firstPage = $pages.first();\n\n\t\t\t// define page container\n\t\t\t$.mobile.pageContainer = $.mobile.firstPage\n\t\t\t\t.parent()\n\t\t\t\t.addClass( \"ui-mobile-viewport\" )\n\t\t\t\t.pagecontainer();\n\n\t\t\t// initialize navigation events now, after mobileinit has occurred and the page container\n\t\t\t// has been created but before the rest of the library is alerted to that fact\n\t\t\t$.mobile.navreadyDeferred.resolve();\n\n\t\t\t// alert listeners that the pagecontainer has been determined for binding\n\t\t\t// to events triggered on it\n\t\t\t$window.trigger( \"pagecontainercreate\" );\n\n\t\t\t// cue page loading message\n\t\t\t$.mobile.loading( \"show\" );\n\n\t\t\t//remove initial build class (only present on first pageshow)\n\t\t\thideRenderingClass();\n\n\t\t\t// if hashchange listening is disabled, there's no hash deeplink,\n\t\t\t// the hash is not valid (contains more than one # or does not start with #)\n\t\t\t// or there is no page with that hash, change to the first page in the DOM\n\t\t\t// Remember, however, that the hash can also be a path!\n\t\t\tif ( ! ( $.mobile.hashListeningEnabled &&\n\t\t\t\t$.mobile.path.isHashValid( location.hash ) &&\n\t\t\t\t( $( hashPage ).is( \":jqmData(role='page')\" ) ||\n\t\t\t\t\t$.mobile.path.isPath( hash ) ||\n\t\t\t\t\thash === $.mobile.dialogHashKey ) ) ) {\n\n\t\t\t\t// make sure to set initial popstate state if it exists\n\t\t\t\t// so that navigation back to the initial page works properly\n\t\t\t\tif ( $.event.special.navigate.isPushStateEnabled() ) {\n\t\t\t\t\t$.mobile.navigate.navigator.squash( path.parseLocation().href );\n\t\t\t\t}\n\n\t\t\t\t$.mobile.changePage( $.mobile.firstPage, {\n\t\t\t\t\ttransition: \"none\",\n\t\t\t\t\treverse: true,\n\t\t\t\t\tchangeHash: false,\n\t\t\t\t\tfromHashChange: true\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// trigger hashchange or navigate to squash and record the correct\n\t\t\t\t// history entry for an initial hash path\n\t\t\t\tif ( !$.event.special.navigate.isPushStateEnabled() ) {\n\t\t\t\t\t$window.trigger( \"hashchange\", [true] );\n\t\t\t\t} else {\n\t\t\t\t\t// TODO figure out how to simplify this interaction with the initial history entry\n\t\t\t\t\t// at the bottom js/navigate/navigate.js\n\t\t\t\t\t$.mobile.navigate.history.stack = [];\n\t\t\t\t\t$.mobile.navigate( $.mobile.path.isPath( location.hash ) ? location.hash : location.href );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t});\n\n\t$(function() {\n\t\t//Run inlineSVG support test\n\t\t$.support.inlineSVG();\n\n\t\t// check which scrollTop value should be used by scrolling to 1 immediately at domready\n\t\t// then check what the scroll top is. Android will report 0... others 1\n\t\t// note that this initial scroll won't hide the address bar. It's just for the check.\n\n\t\t// hide iOS browser chrome on load if hideUrlBar is true this is to try and do it as soon as possible\n\t\tif ( $.mobile.hideUrlBar ) {\n\t\t\twindow.scrollTo( 0, 1 );\n\t\t}\n\n\t\t// if defaultHomeScroll hasn't been set yet, see if scrollTop is 1\n\t\t// it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)\n\t\t// so if it's 1, use 0 from now on\n\t\t$.mobile.defaultHomeScroll = ( !$.support.scrollTop || $.mobile.window.scrollTop() === 1 ) ? 0 : 1;\n\n\t\t//dom-ready inits\n\t\tif ( $.mobile.autoInitializePage ) {\n\t\t\t$.mobile.initializePage();\n\t\t}\n\n\t\t// window load event\n\t\t// hide iOS browser chrome on load if hideUrlBar is true this is as fall back incase we were too early before\n\t\tif ( $.mobile.hideUrlBar ) {\n\t\t\t$window.load( $.mobile.silentScroll );\n\t\t}\n\n\t\tif ( !$.support.cssPointerEvents ) {\n\t\t\t// IE and Opera don't support CSS pointer-events: none that we use to disable link-based buttons\n\t\t\t// by adding the 'ui-disabled' class to them. Using a JavaScript workaround for those browser.\n\t\t\t// https://github.com/jquery/jquery-mobile/issues/3558\n\n\t\t\t// DEPRECATED as of 1.4.0 - remove ui-disabled after 1.4.0 release\n\t\t\t// only ui-state-disabled should be present thereafter\n\t\t\t$.mobile.document.delegate( \".ui-state-disabled,.ui-disabled\", \"vclick\",\n\t\t\t\tfunction( e ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t});\n}( jQuery, this ));\n\n\n}));\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile.external-png-1.4.5.css",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n.ui-icon-action:after {\n\tbackground-image: url(images/icons-png/action-white.png);\n}\n.ui-icon-alert:after {\n\tbackground-image: url(images/icons-png/alert-white.png);\n}\n.ui-icon-arrow-d-l:after {\n\tbackground-image: url(images/icons-png/arrow-d-l-white.png);\n}\n.ui-icon-arrow-d-r:after {\n\tbackground-image: url(images/icons-png/arrow-d-r-white.png);\n}\n.ui-icon-arrow-d:after {\n\tbackground-image: url(images/icons-png/arrow-d-white.png);\n}\n.ui-icon-arrow-l:after {\n\tbackground-image: url(images/icons-png/arrow-l-white.png);\n}\n.ui-icon-arrow-r:after {\n\tbackground-image: url(images/icons-png/arrow-r-white.png);\n}\n.ui-icon-arrow-u-l:after {\n\tbackground-image: url(images/icons-png/arrow-u-l-white.png);\n}\n.ui-icon-arrow-u-r:after {\n\tbackground-image: url(images/icons-png/arrow-u-r-white.png);\n}\n.ui-icon-arrow-u:after {\n\tbackground-image: url(images/icons-png/arrow-u-white.png);\n}\n.ui-icon-audio:after {\n\tbackground-image: url(images/icons-png/audio-white.png);\n}\n.ui-icon-back:after {\n\tbackground-image: url(images/icons-png/back-white.png);\n}\n.ui-icon-bars:after {\n\tbackground-image: url(images/icons-png/bars-white.png);\n}\n.ui-icon-bullets:after {\n\tbackground-image: url(images/icons-png/bullets-white.png);\n}\n.ui-icon-calendar:after {\n\tbackground-image: url(images/icons-png/calendar-white.png);\n}\n.ui-icon-camera:after {\n\tbackground-image: url(images/icons-png/camera-white.png);\n}\n.ui-icon-carat-d:after {\n\tbackground-image: url(images/icons-png/carat-d-white.png);\n}\n.ui-icon-carat-l:after {\n\tbackground-image: url(images/icons-png/carat-l-white.png);\n}\n.ui-icon-carat-r:after {\n\tbackground-image: url(images/icons-png/carat-r-white.png);\n}\n.ui-icon-carat-u:after {\n\tbackground-image: url(images/icons-png/carat-u-white.png);\n}\n.ui-icon-check:after,\n/* Used ui-checkbox-on twice to increase specificity. If active state has background-image for gradient this rule overrides. */\nhtml .ui-btn.ui-checkbox-on.ui-checkbox-on:after {\n\tbackground-image: url(images/icons-png/check-white.png);\n}\n.ui-icon-clock:after {\n\tbackground-image: url(images/icons-png/clock-white.png);\n}\n.ui-icon-cloud:after {\n\tbackground-image: url(images/icons-png/cloud-white.png);\n}\n.ui-icon-comment:after {\n\tbackground-image: url(images/icons-png/comment-white.png);\n}\n.ui-icon-delete:after {\n\tbackground-image: url(images/icons-png/delete-white.png);\n}\n.ui-icon-edit:after {\n\tbackground-image: url(images/icons-png/edit-white.png);\n}\n.ui-icon-eye:after {\n\tbackground-image: url(images/icons-png/eye-white.png);\n}\n.ui-icon-forbidden:after {\n\tbackground-image: url(images/icons-png/forbidden-white.png);\n}\n.ui-icon-forward:after {\n\tbackground-image: url(images/icons-png/forward-white.png);\n}\n.ui-icon-gear:after {\n\tbackground-image: url(images/icons-png/gear-white.png);\n}\n.ui-icon-grid:after {\n\tbackground-image: url(images/icons-png/grid-white.png);\n}\n.ui-icon-heart:after {\n\tbackground-image: url(images/icons-png/heart-white.png);\n}\n.ui-icon-home:after {\n\tbackground-image: url(images/icons-png/home-white.png);\n}\n.ui-icon-info:after {\n\tbackground-image: url(images/icons-png/info-white.png);\n}\n.ui-icon-location:after {\n\tbackground-image: url(images/icons-png/location-white.png);\n}\n.ui-icon-lock:after {\n\tbackground-image: url(images/icons-png/lock-white.png);\n}\n.ui-icon-mail:after {\n\tbackground-image: url(images/icons-png/mail-white.png);\n}\n.ui-icon-minus:after {\n\tbackground-image: url(images/icons-png/minus-white.png);\n}\n.ui-icon-navigation:after {\n\tbackground-image: url(images/icons-png/navigation-white.png);\n}\n.ui-icon-phone:after {\n\tbackground-image: url(images/icons-png/phone-white.png);\n}\n.ui-icon-plus:after {\n\tbackground-image: url(images/icons-png/plus-white.png);\n}\n.ui-icon-power:after {\n\tbackground-image: url(images/icons-png/power-white.png);\n}\n.ui-icon-recycle:after {\n\tbackground-image: url(images/icons-png/recycle-white.png);\n}\n.ui-icon-refresh:after {\n\tbackground-image: url(images/icons-png/refresh-white.png);\n}\n.ui-icon-search:after {\n\tbackground-image: url(images/icons-png/search-white.png);\n}\n.ui-icon-shop:after {\n\tbackground-image: url(images/icons-png/shop-white.png);\n}\n.ui-icon-star:after {\n\tbackground-image: url(images/icons-png/star-white.png);\n}\n.ui-icon-tag:after {\n\tbackground-image: url(images/icons-png/tag-white.png);\n}\n.ui-icon-user:after {\n\tbackground-image: url(images/icons-png/user-white.png);\n}\n.ui-icon-video:after {\n\tbackground-image: url(images/icons-png/video-white.png);\n}\n/* Alt icons */\n.ui-alt-icon.ui-icon-action:after,\n.ui-alt-icon .ui-icon-action:after {\n\tbackground-image: url(images/icons-png/action-black.png);\n}\n.ui-alt-icon.ui-icon-alert:after,\n.ui-alt-icon .ui-icon-alert:after {\n\tbackground-image: url(images/icons-png/alert-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-d:after,\n.ui-alt-icon .ui-icon-arrow-d:after {\n\tbackground-image: url(images/icons-png/arrow-d-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-d-l:after,\n.ui-alt-icon .ui-icon-arrow-d-l:after {\n\tbackground-image: url(images/icons-png/arrow-d-l-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-d-r:after,\n.ui-alt-icon .ui-icon-arrow-d-r:after {\n\tbackground-image: url(images/icons-png/arrow-d-r-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-l:after,\n.ui-alt-icon .ui-icon-arrow-l:after {\n\tbackground-image: url(images/icons-png/arrow-l-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-r:after,\n.ui-alt-icon .ui-icon-arrow-r:after {\n\tbackground-image: url(images/icons-png/arrow-r-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-u:after,\n.ui-alt-icon .ui-icon-arrow-u:after {\n\tbackground-image: url(images/icons-png/arrow-u-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-u-l:after,\n.ui-alt-icon .ui-icon-arrow-u-l:after {\n\tbackground-image: url(images/icons-png/arrow-u-l-black.png);\n}\n.ui-alt-icon.ui-icon-arrow-u-r:after,\n.ui-alt-icon .ui-icon-arrow-u-r:after {\n\tbackground-image: url(images/icons-png/arrow-u-r-black.png);\n}\n.ui-alt-icon.ui-icon-audio:after,\n.ui-alt-icon .ui-icon-audio:after {\n\tbackground-image: url(images/icons-png/audio-black.png);\n}\n.ui-alt-icon.ui-icon-back:after,\n.ui-alt-icon .ui-icon-back:after {\n\tbackground-image: url(images/icons-png/back-black.png);\n}\n.ui-alt-icon.ui-icon-bars:after,\n.ui-alt-icon .ui-icon-bars:after {\n\tbackground-image: url(images/icons-png/bars-black.png);\n}\n.ui-alt-icon.ui-icon-bullets:after,\n.ui-alt-icon .ui-icon-bullets:after {\n\tbackground-image: url(images/icons-png/bullets-black.png);\n}\n.ui-alt-icon.ui-icon-calendar:after,\n.ui-alt-icon .ui-icon-calendar:after {\n\tbackground-image: url(images/icons-png/calendar-black.png);\n}\n.ui-alt-icon.ui-icon-camera:after,\n.ui-alt-icon .ui-icon-camera:after {\n\tbackground-image: url(images/icons-png/camera-black.png);\n}\n.ui-alt-icon.ui-icon-carat-d:after,\n.ui-alt-icon .ui-icon-carat-d:after {\n\tbackground-image: url(images/icons-png/carat-d-black.png);\n}\n.ui-alt-icon.ui-icon-carat-l:after,\n.ui-alt-icon .ui-icon-carat-l:after {\n\tbackground-image: url(images/icons-png/carat-l-black.png);\n}\n.ui-alt-icon.ui-icon-carat-r:after,\n.ui-alt-icon .ui-icon-carat-r:after {\n\tbackground-image: url(images/icons-png/carat-r-black.png);\n}\n.ui-alt-icon.ui-icon-carat-u:after,\n.ui-alt-icon .ui-icon-carat-u:after {\n\tbackground-image: url(images/icons-png/carat-u-black.png);\n}\n.ui-alt-icon.ui-icon-check:after,\n.ui-alt-icon .ui-icon-check:after,\nhtml .ui-alt-icon.ui-btn.ui-checkbox-on:after,\nhtml .ui-alt-icon .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(images/icons-png/check-black.png);\n}\n.ui-alt-icon.ui-icon-clock:after,\n.ui-alt-icon .ui-icon-clock:after {\n\tbackground-image: url(images/icons-png/clock-black.png);\n}\n.ui-alt-icon.ui-icon-cloud:after,\n.ui-alt-icon .ui-icon-cloud:after {\n\tbackground-image: url(images/icons-png/cloud-black.png);\n}\n.ui-alt-icon.ui-icon-comment:after,\n.ui-alt-icon .ui-icon-comment:after {\n\tbackground-image: url(images/icons-png/comment-black.png);\n}\n.ui-alt-icon.ui-icon-delete:after,\n.ui-alt-icon .ui-icon-delete:after {\n\tbackground-image: url(images/icons-png/delete-black.png);\n}\n.ui-alt-icon.ui-icon-edit:after,\n.ui-alt-icon .ui-icon-edit:after {\n\tbackground-image: url(images/icons-png/edit-black.png);\n}\n.ui-alt-icon.ui-icon-eye:after,\n.ui-alt-icon .ui-icon-eye:after {\n\tbackground-image: url(images/icons-png/eye-black.png);\n}\n.ui-alt-icon.ui-icon-forbidden:after,\n.ui-alt-icon .ui-icon-forbidden:after {\n\tbackground-image: url(images/icons-png/forbidden-black.png);\n}\n.ui-alt-icon.ui-icon-forward:after,\n.ui-alt-icon .ui-icon-forward:after {\n\tbackground-image: url(images/icons-png/forward-black.png);\n}\n.ui-alt-icon.ui-icon-gear:after,\n.ui-alt-icon .ui-icon-gear:after {\n\tbackground-image: url(images/icons-png/gear-black.png);\n}\n.ui-alt-icon.ui-icon-grid:after,\n.ui-alt-icon .ui-icon-grid:after {\n\tbackground-image: url(images/icons-png/grid-black.png);\n}\n.ui-alt-icon.ui-icon-heart:after,\n.ui-alt-icon .ui-icon-heart:after {\n\tbackground-image: url(images/icons-png/heart-black.png);\n}\n.ui-alt-icon.ui-icon-home:after,\n.ui-alt-icon .ui-icon-home:after {\n\tbackground-image: url(images/icons-png/home-black.png);\n}\n.ui-alt-icon.ui-icon-info:after,\n.ui-alt-icon .ui-icon-info:after {\n\tbackground-image: url(images/icons-png/info-black.png);\n}\n.ui-alt-icon.ui-icon-location:after,\n.ui-alt-icon .ui-icon-location:after {\n\tbackground-image: url(images/icons-png/location-black.png);\n}\n.ui-alt-icon.ui-icon-lock:after,\n.ui-alt-icon .ui-icon-lock:after {\n\tbackground-image: url(images/icons-png/lock-black.png);\n}\n.ui-alt-icon.ui-icon-mail:after,\n.ui-alt-icon .ui-icon-mail:after {\n\tbackground-image: url(images/icons-png/mail-black.png);\n}\n.ui-alt-icon.ui-icon-minus:after,\n.ui-alt-icon .ui-icon-minus:after {\n\tbackground-image: url(images/icons-png/minus-black.png);\n}\n.ui-alt-icon.ui-icon-navigation:after,\n.ui-alt-icon .ui-icon-navigation:after {\n\tbackground-image: url(images/icons-png/navigation-black.png);\n}\n.ui-alt-icon.ui-icon-phone:after,\n.ui-alt-icon .ui-icon-phone:after {\n\tbackground-image: url(images/icons-png/phone-black.png);\n}\n.ui-alt-icon.ui-icon-plus:after,\n.ui-alt-icon .ui-icon-plus:after {\n\tbackground-image: url(images/icons-png/plus-black.png);\n}\n.ui-alt-icon.ui-icon-power:after,\n.ui-alt-icon .ui-icon-power:after {\n\tbackground-image: url(images/icons-png/power-black.png);\n}\n.ui-alt-icon.ui-icon-recycle:after,\n.ui-alt-icon .ui-icon-recycle:after {\n\tbackground-image: url(images/icons-png/recycle-black.png);\n}\n.ui-alt-icon.ui-icon-refresh:after,\n.ui-alt-icon .ui-icon-refresh:after {\n\tbackground-image: url(images/icons-png/refresh-black.png);\n}\n.ui-alt-icon.ui-icon-search:after,\n.ui-alt-icon .ui-icon-search:after,\n.ui-input-search:after {\n\tbackground-image: url(images/icons-png/search-black.png);\n}\n.ui-alt-icon.ui-icon-shop:after,\n.ui-alt-icon .ui-icon-shop:after {\n\tbackground-image: url(images/icons-png/shop-black.png);\n}\n.ui-alt-icon.ui-icon-star:after,\n.ui-alt-icon .ui-icon-star:after {\n\tbackground-image: url(images/icons-png/star-black.png);\n}\n.ui-alt-icon.ui-icon-tag:after,\n.ui-alt-icon .ui-icon-tag:after {\n\tbackground-image: url(images/icons-png/tag-black.png);\n}\n.ui-alt-icon.ui-icon-user:after,\n.ui-alt-icon .ui-icon-user:after {\n\tbackground-image: url(images/icons-png/user-black.png);\n}\n.ui-alt-icon.ui-icon-video:after,\n.ui-alt-icon .ui-icon-video:after {\n\tbackground-image: url(images/icons-png/video-black.png);\n}\n/* Globals */\n/* Font\n-----------------------------------------------------------------------------------------------------------*/\nhtml {\n\tfont-size: 100%;\n}\nbody,\ninput,\nselect,\ntextarea,\nbutton,\n.ui-btn {\n\tfont-size: 1em;\n\tline-height: 1.3;\n\tfont-family: sans-serif /*{global-font-family}*/;\n}\nlegend,\n.ui-input-text input,\n.ui-input-search input {\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n/* Form labels (overrides font-weight bold in bars, and mini font-size) */\n.ui-mobile label,\ndiv.ui-controlgroup-label {\n\tfont-weight: normal;\n\tfont-size: 16px;\n}\n/* Separators\n-----------------------------------------------------------------------------------------------------------*/\n/* Field contain separator (< 28em) */\n.ui-field-contain {\n\tborder-bottom-color: #828282;\n\tborder-bottom-color: rgba(0,0,0,.15);\n\tborder-bottom-width: 1px;\n\tborder-bottom-style: solid;\n}\n/* Table opt-in classes: strokes between each row, and alternating row stripes */\n/* Classes table-stroke and table-stripe are deprecated in 1.4. */\n.table-stroke thead th,\n.table-stripe thead th,\n.table-stripe tbody tr:last-child {\n\tborder-bottom: 1px solid #d6d6d6; /* non-RGBA fallback */\n\tborder-bottom: 1px solid rgba(0,0,0,.1);\n}\n.table-stroke tbody th,\n.table-stroke tbody td {\n\tborder-bottom: 1px solid #e6e6e6; /* non-RGBA fallback  */\n\tborder-bottom: 1px solid rgba(0,0,0,.05);\n}\n.table-stripe.table-stroke tbody tr:last-child th,\n.table-stripe.table-stroke tbody tr:last-child td {\n\tborder-bottom: 0;\n}\n.table-stripe tbody tr:nth-child(odd) td,\n.table-stripe tbody tr:nth-child(odd) th {\n\tbackground-color: #eeeeee; /* non-RGBA fallback  */\n\tbackground-color: rgba(0,0,0,.04);\n}\n/* Buttons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn,\nlabel.ui-btn {\n\tfont-weight: bold;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-btn {\n\ttext-decoration: none !important;\n}\n.ui-btn-active {\n\tcursor: pointer;\n}\n/* Corner rounding\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-btn-corner-all deprecated in 1.4 */\n.ui-corner-all {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-blocks}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-blocks}*/;\n}\n/* Buttons */\n.ui-btn-corner-all,\n.ui-btn.ui-corner-all,\n/* Slider track */\n.ui-slider-track.ui-corner-all,\n/* Flipswitch */\n.ui-flipswitch.ui-corner-all,\n/* Count bubble */\n.ui-li-count {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-buttons}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-buttons}*/;\n}\n/* Icon-only buttons */\n.ui-btn-icon-notext.ui-btn-corner-all,\n.ui-btn-icon-notext.ui-corner-all {\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Radius clip workaround for cleaning up corner trapping */\n.ui-btn-corner-all,\n.ui-corner-all {\n\t-webkit-background-clip: padding;\n\tbackground-clip: padding-box;\n}\n/* Popup arrow */\n.ui-popup.ui-corner-all > .ui-popup-arrow-guide {\n\tleft: .6em /*{global-radii-blocks}*/;\n\tright: .6em /*{global-radii-blocks}*/;\n\ttop: .6em /*{global-radii-blocks}*/;\n\tbottom: .6em /*{global-radii-blocks}*/;\n}\n/* Shadow\n-----------------------------------------------------------------------------------------------------------*/\n.ui-shadow {\n\t-webkit-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\tbox-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\t\t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n}\n.ui-shadow-inset {\n\t-webkit-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\tbox-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n}\n.ui-overlay-shadow {\n\t-webkit-box-shadow: 0 0 12px \t\trgba(0,0,0,.6);\n\t-moz-box-shadow: 0 0 12px \t\t\trgba(0,0,0,.6);\n\tbox-shadow: 0 0 12px \t\t\t\trgba(0,0,0,.6);\n}\n/* Icons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.3) /*{global-icon-disc}*/;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Alt icons */\n.ui-alt-icon.ui-btn:after,\n.ui-alt-icon .ui-btn:after,\nhtml .ui-alt-icon.ui-checkbox-off:after,\nhtml .ui-alt-icon.ui-radio-off:after,\nhtml .ui-alt-icon .ui-checkbox-off:after,\nhtml .ui-alt-icon .ui-radio-off:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.15) /*{global-icon-disc}*/;\n}\n/* No disc */\n.ui-nodisc-icon.ui-btn:after,\n.ui-nodisc-icon .ui-btn:after {\n\tbackground-color: transparent;\n}\n/* Icon shadow */\n.ui-shadow-icon.ui-btn:after,\n.ui-shadow-icon .ui-btn:after {\n\t-webkit-box-shadow: 0 1px 0 \t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\t-moz-box-shadow: 0 1px 0 \t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\tbox-shadow: 0 1px 0 \t\t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n}\n/* Checkbox and radio */\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after,\n.ui-btn.ui-radio-off:after,\n.ui-btn.ui-radio-on:after {\n\tdisplay: block;\n\twidth: 18px;\n\theight: 18px;\n\tmargin: -9px 2px 0 2px;\n}\n.ui-checkbox-off:after,\n.ui-btn.ui-radio-off:after {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n}\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after {\n\t-webkit-border-radius: .1875em;\n\tborder-radius: .1875em;\n}\n.ui-btn.ui-checkbox-off:after {\n\tbackground-color: #666;\n\tbackground-color: rgba(0,0,0,.3);\n}\n.ui-radio .ui-btn.ui-radio-on:after {\n\tbackground-image: none;\n\tbackground-color: #fff;\n\twidth: 8px;\n\theight: 8px;\n\tborder-width: 5px;\n\tborder-style: solid; \n}\n.ui-alt-icon.ui-btn.ui-radio-on:after,\n.ui-alt-icon .ui-btn.ui-radio-on:after {\n\tbackground-color: #000;\n}\n/* Loader */\n.ui-icon-loading {\n\tbackground: url(images/ajax-loader.gif);\n\tbackground-size: 2.875em 2.875em;\n}\n/* Swatches */\n/* A\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-a,\n.ui-page-theme-a .ui-bar-inherit,\nhtml .ui-bar-a .ui-bar-inherit,\nhtml .ui-body-a .ui-bar-inherit,\nhtml body .ui-group-theme-a .ui-bar-inherit {\n\tbackground-color: \t\t\t#e9e9e9 /*{a-bar-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bar-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bar-color}*/;\n\ttext-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 0 /*{a-bar-shadow-radius}*/ \t#eee /*{a-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-a,\n.ui-page-theme-a,\n.ui-page-theme-a .ui-panel-wrapper {\n\tbackground-color: \t\t\t#f9f9f9 /*{a-page-background-color}*/;\n\tborder-color:\t \t\t#bbb /*{a-page-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-page-color}*/;\n\ttext-shadow: 0 /*{a-page-shadow-x}*/ 1px /*{a-page-shadow-y}*/ 0 /*{a-page-shadow-radius}*/ \t#f3f3f3 /*{a-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-a,\n.ui-page-theme-a .ui-body-inherit,\nhtml .ui-bar-a .ui-body-inherit,\nhtml .ui-body-a .ui-body-inherit,\nhtml body .ui-group-theme-a .ui-body-inherit,\nhtml .ui-panel-page-container-a {\n\tbackground-color: \t\t\t#fff /*{a-body-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-body-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-body-color}*/;\n\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ \t#f3f3f3 /*{a-body-shadow-color}*/;\n}\n.ui-body-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-a a,\nhtml .ui-bar-a a,\nhtml .ui-body-a a,\nhtml body .ui-group-theme-a a {\n\tcolor: #3388cc /*{a-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-a a:visited,\nhtml .ui-bar-a a:visited,\nhtml .ui-body-a a:visited,\nhtml body .ui-group-theme-a a:visited {\n    color: #3388cc /*{a-link-visited}*/;\n}\n.ui-page-theme-a a:hover,\nhtml .ui-bar-a a:hover,\nhtml .ui-body-a a:hover,\nhtml body .ui-group-theme-a a:hover {\n\tcolor: #005599 /*{a-link-hover}*/;\n}\n.ui-page-theme-a a:active,\nhtml .ui-bar-a a:active,\nhtml .ui-body-a a:active,\nhtml body .ui-group-theme-a a:active {\n\tcolor: #005599 /*{a-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-a .ui-btn,\nhtml .ui-bar-a .ui-btn,\nhtml .ui-body-a .ui-btn,\nhtml body .ui-group-theme-a .ui-btn,\nhtml head + body .ui-btn.ui-btn-a,\n/* Button visited */\n.ui-page-theme-a .ui-btn:visited,\nhtml .ui-bar-a .ui-btn:visited,\nhtml .ui-body-a .ui-btn:visited,\nhtml body .ui-group-theme-a .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-a:visited {\n\tbackground-color: \t\t\t#f6f6f6 /*{a-bup-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bup-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bup-color}*/;\n\ttext-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #f3f3f3 /*{a-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-a .ui-btn:hover,\nhtml .ui-bar-a .ui-btn:hover,\nhtml .ui-body-a .ui-btn:hover,\nhtml body .ui-group-theme-a .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-a:hover {\n\tbackground-color: \t\t\t#ededed /*{a-bhover-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bhover-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bhover-color}*/;\n\ttext-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #f3f3f3 /*{a-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-a .ui-btn:active,\nhtml .ui-bar-a .ui-btn:active,\nhtml .ui-body-a .ui-btn:active,\nhtml body .ui-group-theme-a .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-a:active {\n\tbackground-color: \t\t\t#e8e8e8 /*{a-bdown-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bdown-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bdown-color}*/;\n\ttext-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #f3f3f3 /*{a-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-a .ui-btn.ui-btn-active,\nhtml .ui-bar-a .ui-btn.ui-btn-active,\nhtml .ui-body-a .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-a .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-a.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-a .ui-checkbox-on:after,\nhtml .ui-bar-a .ui-checkbox-on:after,\nhtml .ui-body-a .ui-checkbox-on:after,\nhtml body .ui-group-theme-a .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-a:after,\n/* Active flipswitch background */\n.ui-page-theme-a .ui-flipswitch-active,\nhtml .ui-bar-a .ui-flipswitch-active,\nhtml .ui-body-a .ui-flipswitch-active,\nhtml body .ui-group-theme-a .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-a .ui-slider-track .ui-btn-active,\nhtml .ui-bar-a .ui-slider-track .ui-btn-active,\nhtml .ui-body-a .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-a .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-a .ui-btn-active {\n\tbackground-color: \t\t#3388cc /*{a-active-background-color}*/;\n\tborder-color:\t \t\t#3388cc /*{a-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{a-active-color}*/;\n\ttext-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #005599 /*{a-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-a .ui-radio-on:after,\nhtml .ui-bar-a .ui-radio-on:after,\nhtml .ui-body-a .ui-radio-on:after,\nhtml body .ui-group-theme-a .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-a:after {\n\tborder-color:\t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-a .ui-btn:focus,\nhtml .ui-bar-a .ui-btn:focus,\nhtml .ui-body-a .ui-btn:focus,\nhtml body .ui-group-theme-a .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-a:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-a .ui-focus,\nhtml .ui-bar-a .ui-focus,\nhtml .ui-body-a .ui-focus,\nhtml body .ui-group-theme-a .ui-focus,\nhtml head + body .ui-btn-a.ui-focus,\nhtml head + body .ui-body-a.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#3388cc /*{a-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#3388cc /*{a-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* B\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-b,\n.ui-page-theme-b .ui-bar-inherit,\nhtml .ui-bar-b .ui-bar-inherit,\nhtml .ui-body-b .ui-bar-inherit,\nhtml body .ui-group-theme-b .ui-bar-inherit {\n\tbackground-color: \t\t\t#1d1d1d /*{b-bar-background-color}*/;\n\tborder-color:\t \t\t#1b1b1b /*{b-bar-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bar-color}*/;\n\ttext-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 0 /*{b-bar-shadow-radius}*/ \t#111 /*{b-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-b,\n.ui-page-theme-b,\n.ui-page-theme-b .ui-panel-wrapper {\n\tbackground-color: \t\t\t#252525 /*{b-page-background-color}*/;\n\tborder-color:\t \t\t#454545 /*{b-page-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-page-color}*/;\n\ttext-shadow: 0 /*{b-page-shadow-x}*/ 1px /*{b-page-shadow-y}*/ 0 /*{b-page-shadow-radius}*/ \t#111 /*{b-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-b,\n.ui-page-theme-b .ui-body-inherit,\nhtml .ui-bar-b .ui-body-inherit,\nhtml .ui-body-b .ui-body-inherit,\nhtml body .ui-group-theme-b .ui-body-inherit,\nhtml .ui-panel-page-container-b {\n\tbackground-color: \t\t\t#2a2a2a /*{b-body-background-color}*/;\n\tborder-color:\t \t\t#1d1d1d /*{b-body-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-body-color}*/;\n\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ \t#111 /*{b-body-shadow-color}*/;\n}\n.ui-body-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-b a,\nhtml .ui-bar-b a,\nhtml .ui-body-b a,\nhtml body .ui-group-theme-b a {\n\tcolor: #22aadd /*{b-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-b a:visited,\nhtml .ui-bar-b a:visited,\nhtml .ui-body-b a:visited,\nhtml body .ui-group-theme-b a:visited {\n    color: #22aadd /*{b-link-visited}*/;\n}\n.ui-page-theme-b a:hover,\nhtml .ui-bar-b a:hover,\nhtml .ui-body-b a:hover,\nhtml body .ui-group-theme-b a:hover {\n\tcolor: #0088bb /*{b-link-hover}*/;\n}\n.ui-page-theme-b a:active,\nhtml .ui-bar-b a:active,\nhtml .ui-body-b a:active,\nhtml body .ui-group-theme-b a:active {\n\tcolor: #0088bb /*{b-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-b .ui-btn,\nhtml .ui-bar-b .ui-btn,\nhtml .ui-body-b .ui-btn,\nhtml body .ui-group-theme-b .ui-btn,\nhtml head + body .ui-btn.ui-btn-b,\n/* Button visited */\n.ui-page-theme-b .ui-btn:visited,\nhtml .ui-bar-b .ui-btn:visited,\nhtml .ui-body-b .ui-btn:visited,\nhtml body .ui-group-theme-b .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-b:visited {\n\tbackground-color: \t\t\t#333 /*{b-bup-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bup-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n\ttext-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #111 /*{b-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-b .ui-btn:hover,\nhtml .ui-bar-b .ui-btn:hover,\nhtml .ui-body-b .ui-btn:hover,\nhtml body .ui-group-theme-b .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-b:hover {\n\tbackground-color: \t\t\t#373737 /*{b-bhover-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bhover-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n\ttext-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #111 /*{b-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-b .ui-btn:active,\nhtml .ui-bar-b .ui-btn:active,\nhtml .ui-body-b .ui-btn:active,\nhtml body .ui-group-theme-b .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-b:active {\n\tbackground-color: \t\t\t#404040 /*{b-bdown-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bdown-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n\ttext-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #111 /*{b-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-b .ui-btn.ui-btn-active,\nhtml .ui-bar-b .ui-btn.ui-btn-active,\nhtml .ui-body-b .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-b .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-b.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-b .ui-checkbox-on:after,\nhtml .ui-bar-b .ui-checkbox-on:after,\nhtml .ui-body-b .ui-checkbox-on:after,\nhtml body .ui-group-theme-b .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-b:after,\n/* Active flipswitch background */\n.ui-page-theme-b .ui-flipswitch-active,\nhtml .ui-bar-b .ui-flipswitch-active,\nhtml .ui-body-b .ui-flipswitch-active,\nhtml body .ui-group-theme-b .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-b .ui-slider-track .ui-btn-active,\nhtml .ui-bar-b .ui-slider-track .ui-btn-active,\nhtml .ui-body-b .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-b .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-b .ui-btn-active {\n\tbackground-color: \t\t#22aadd /*{b-active-background-color}*/;\n\tborder-color:\t \t\t#22aadd /*{b-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-active-color}*/;\n\ttext-shadow: 0 /*{b-active-shadow-x}*/ 1px /*{b-active-shadow-y}*/ 0 /*{b-active-shadow-radius}*/ #0088bb /*{b-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-b .ui-radio-on:after,\nhtml .ui-bar-b .ui-radio-on:after,\nhtml .ui-body-b .ui-radio-on:after,\nhtml body .ui-group-theme-b .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-b:after {\n\tborder-color:\t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-b .ui-btn:focus,\nhtml .ui-bar-b .ui-btn:focus,\nhtml .ui-body-b .ui-btn:focus,\nhtml body .ui-group-theme-b .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-b:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-b .ui-focus,\nhtml .ui-bar-b .ui-focus,\nhtml .ui-body-b .ui-focus,\nhtml body .ui-group-theme-b .ui-focus,\nhtml head + body .ui-btn-b.ui-focus,\nhtml head + body .ui-body-b.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#22aadd /*{b-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#22aadd /*{b-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Structure */\n/* Disabled\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-disabled deprecated in 1.4. :disabled not supported by IE8 so we use [disabled] */\n.ui-disabled,\n.ui-state-disabled,\nbutton[disabled],\n.ui-select .ui-btn.ui-state-disabled {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n\tcursor: default !important;\n\tpointer-events: none;\n}\n/* Focus state outline\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn:focus,\n.ui-btn.ui-focus {\n\toutline: 0;\n}\n/* Unset box-shadow in browsers that don't do it right */\n.ui-noboxshadow .ui-shadow,\n.ui-noboxshadow .ui-shadow-inset,\n.ui-noboxshadow .ui-overlay-shadow,\n.ui-noboxshadow .ui-shadow-icon.ui-btn:after,\n.ui-noboxshadow .ui-shadow-icon .ui-btn:after,\n.ui-noboxshadow .ui-focus,\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow  input:focus,\n.ui-noboxshadow .ui-panel {\n\t-webkit-box-shadow: none !important;\n\t-moz-box-shadow: none !important;\n\tbox-shadow: none !important;\n}\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow .ui-focus {\n\toutline-width: 1px;\n\toutline-style: auto;\n}\n/* Some unsets */\n.ui-mobile,\n.ui-mobile body {\n\theight: 99.9%;\n}\n.ui-mobile fieldset,\n.ui-page {\n\tpadding: 0;\n\tmargin: 0;\n}\n.ui-mobile a img,\n.ui-mobile fieldset {\n\tborder-width: 0;\n}\n/* Fixes for fieldset issues on IE10 and FF (see #6077) */\n.ui-mobile fieldset {\n\tmin-width: 0;\n}\n@-moz-document url-prefix() {\n\t.ui-mobile fieldset {\n\t\tdisplay: table-column;\n\t\tvertical-align: middle;\n\t}\n}\n/* Viewport */\n.ui-mobile-viewport {\n\tmargin: 0;\n\toverflow-x: visible;\n\t-webkit-text-size-adjust: 100%;\n\t-ms-text-size-adjust:none;\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n/* Issue #2066 */\nbody.ui-mobile-viewport,\ndiv.ui-mobile-viewport {\n\toverflow-x: hidden;\n}\n/* \"page\" containers - full-screen views, one should always be in view post-pageload */\n.ui-mobile [data-role=page],\n.ui-mobile [data-role=dialog],\n.ui-page {\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 100%;\n\tposition: absolute;\n\tdisplay: none;\n\tborder: 0;\n}\n/* On ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */\n.ui-page {\n\toutline: none;\n}\n.ui-mobile .ui-page-active {\n\tdisplay: block;\n\toverflow: visible;\n\toverflow-x: hidden;\n}\n@media screen and (orientation: portrait) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 420px;\n\t}\n}\n@media screen and (orientation: landscape) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 300px;\n\t}\n}\n/* Fouc */\n.ui-mobile-rendering > * {\n\tvisibility: hidden;\n}\n/* Non-js content hiding */\n.ui-nojs {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Loading screen */\n.ui-loading .ui-loader {\n\tdisplay: block;\n}\n.ui-loader {\n\tdisplay: none;\n\tz-index: 9999999;\n\tposition: fixed;\n\ttop: 50%;\n\tleft: 50%;\n\tborder:0;\n}\n.ui-loader-default {\n\tbackground: none;\n\tfilter: Alpha(Opacity=18);\n\topacity: .18;\n\twidth: 2.875em;\n\theight: 2.875em;\n\tmargin-left: -1.4375em;\n\tmargin-top: -1.4375em;\n}\n.ui-loader-verbose {\n\twidth: 12.5em;\n\tfilter: Alpha(Opacity=88);\n\topacity: .88;\n\tbox-shadow: 0 1px 1px -1px #fff;\n\theight: auto;\n\tmargin-left: -6.875em;\n\tmargin-top: -2.6875em;\n\tpadding: .625em;\n}\n.ui-loader-default h1 {\n\tfont-size: 0;\n\twidth: 0;\n\theight: 0;\n\toverflow: hidden;\n}\n.ui-loader-verbose h1 {\n\tfont-size: 1em;\n\tmargin: 0;\n\ttext-align: center;\n}\n.ui-loader .ui-icon-loading {\n\tbackground-color: #000;\n\tdisplay: block;\n\tmargin: 0;\n\twidth: 2.75em;\n\theight: 2.75em;\n\tpadding: .0625em;\n\t-webkit-border-radius: 2.25em;\n\tborder-radius: 2.25em;\n}\n.ui-loader-verbose .ui-icon-loading {\n\tmargin: 0 auto .625em;\n\tfilter: Alpha(Opacity=75);\n\topacity: .75;\n}\n.ui-loader-textonly {\n\tpadding: .9375em;\n\tmargin-left: -7.1875em;\n}\n.ui-loader-textonly .ui-icon-loading {\n\tdisplay: none;\n}\n.ui-loader-fakefix {\n\tposition: absolute;\n}\n/* Headers, content panels */\n.ui-bar,\n.ui-body {\n\tposition: relative;\n\tpadding: .4em 1em;\n\toverflow: hidden;\n\tdisplay: block;\n\tclear: both;\n}\n.ui-bar h1,\n.ui-bar h2,\n.ui-bar h3,\n.ui-bar h4,\n.ui-bar h5,\n.ui-bar h6 {\n\tmargin: 0;\n\tpadding: 0;\n\tfont-size: 1em;\n\tdisplay: inline-block;\n}\n.ui-header,\n.ui-footer {\n\tborder-width: 1px 0;\n\tborder-style: solid;\n\tposition: relative;\n}\n.ui-header:empty,\n.ui-footer:empty {\n\tmin-height: 2.6875em;\n}\n.ui-header .ui-title,\n.ui-footer .ui-title {\n\tfont-size: 1em;\n\tmin-height: 1.1em;\n\ttext-align: center;\n\tdisplay: block;\n\tmargin: 0 30%;\n\tpadding: .7em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\toutline: 0 !important;\n}\n.ui-footer .ui-title {\n\tmargin: 0 1em;\n}\n.ui-content {\n\tborder-width: 0;\n\toverflow: visible;\n\toverflow-x: hidden;\n\tpadding: 1em;\n}\n/* Corner styling for dialogs and popups */\n.ui-corner-all > .ui-header:first-child,\n.ui-corner-all > .ui-content:first-child,\n.ui-corner-all > .ui-footer:first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-corner-all > .ui-header:last-child,\n.ui-corner-all > .ui-content:last-child,\n.ui-corner-all > .ui-footer:last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n/* Buttons and icons */\n.ui-btn {\n\tfont-size: 16px;\n\tmargin: .5em 0;\n\tpadding: .7em 1em;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: center;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\tcursor: pointer;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n.ui-btn-icon-notext,\n.ui-header button.ui-btn.ui-btn-icon-notext,\n.ui-footer button.ui-btn.ui-btn-icon-notext {\n\tpadding: 0;\n\twidth: 1.75em;\n\theight: 1.75em;\n\ttext-indent: -9999px;\n\twhite-space: nowrap !important;\n}\n.ui-mini {\n\tfont-size: 12.5px;\n}\n.ui-mini .ui-btn {\n\tfont-size: inherit;\n}\n/* Make buttons in toolbars default to mini and inline. */\n.ui-header .ui-btn,\n.ui-footer .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-header .ui-controlgroup .ui-btn-icon-notext,\n.ui-footer .ui-controlgroup .ui-btn-icon-notext {\n    font-size: 12.5px;\n}\n/* To ensure same top and left/right position when ui-btn-left/right are added to something other than buttons. */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right {\n\tfont-size: 12.5px;\n}\n.ui-mini.ui-btn-icon-notext,\n.ui-mini .ui-btn-icon-notext,\n.ui-header .ui-btn-icon-notext,\n.ui-footer .ui-btn-icon-notext {\n\tfont-size: 16px;\t\n\tpadding: 0;\n}\n.ui-btn-inline {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin-right: .625em;\n}\n.ui-btn-icon-left {\n\tpadding-left: 2.5em;\n}\n.ui-btn-icon-right {\n\tpadding-right: 2.5em;\n}\n.ui-btn-icon-top {\n\tpadding-top: 2.5em;\n}\n.ui-btn-icon-bottom {\n\tpadding-bottom: 2.5em;\n}\n.ui-header .ui-btn-icon-top,\n.ui-footer .ui-btn-icon-top,\n.ui-header .ui-btn-icon-bottom,\n.ui-footer .ui-btn-icon-bottom {\n\tpadding-left: .3125em;\n\tpadding-right: .3125em;\n}\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tcontent: \"\";\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 22px;\n\theight: 22px;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after {\n\ttop: 50%;\n\tmargin-top: -11px;\n}\n.ui-btn-icon-left:after {\n\tleft: .5625em;\n}\n.ui-btn-icon-right:after {\n\tright: .5625em;\n}\n.ui-mini.ui-btn-icon-left:after,\n.ui-mini .ui-btn-icon-left:after,\n.ui-header .ui-btn-icon-left:after,\n.ui-footer .ui-btn-icon-left:after {\n\tleft: .37em;\n}\n.ui-mini.ui-btn-icon-right:after,\n.ui-mini .ui-btn-icon-right:after,\n.ui-header .ui-btn-icon-right:after,\n.ui-footer .ui-btn-icon-right:after {\n\tright: .37em;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after {\n\tleft: 50%;\n\tmargin-left: -11px;\n}\n.ui-btn-icon-top:after {\n\ttop: .5625em;\n}\n.ui-btn-icon-bottom:after {\n\ttop: auto;\n\tbottom: .5625em;\n}\n/* Buttons in header position classes */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right,\n.ui-btn-left > [class*=\"ui-\"],\n.ui-btn-right > [class*=\"ui-\"] {\n\tmargin: 0;\n}\n.ui-btn-left,\n.ui-btn-right {\n\tposition: absolute;\n\ttop: .24em;\n}\n.ui-btn-left {\n\tleft: .4em;\n}\n.ui-btn-right {\n\tright: .4em;\n}\n.ui-btn-icon-notext.ui-btn-left {\n\ttop: .3125em;\n\tleft: .3125em;\n}\n.ui-btn-icon-notext.ui-btn-right {\n\ttop: .3125em;\n\tright: .3125em;\n}\n/* Button elements */\nbutton.ui-btn,\n.ui-controlgroup-controls button.ui-btn-icon-notext {\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\twidth: 100%;\n}\nbutton.ui-btn-inline,\n.ui-header button.ui-btn,\n.ui-footer button.ui-btn {\n\twidth: auto;\n}\n/* Firefox adds a 1px border in a button element. We negate this to make sure they have the same height as other buttons in controlgroups. */\nbutton.ui-btn::-moz-focus-inner {\n\tborder: 0;\n}\nbutton.ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn {\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n\twidth: 1.75em;\n}\n/* Form labels */\n.ui-mobile label,\n.ui-controlgroup-label {\n\tdisplay: block;\n\tmargin: 0 0 .4em;\n}\n/* Accessible content hiding */\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-hide-label > label,\n.ui-hide-label .ui-controlgroup-label,\n.ui-hide-label .ui-rangeslider label,\n.ui-hidden-accessible {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Used for hiding elements by the filterable widget. You can also use this class to hide list items or buttons in controlgroups; this ensures correct corner styling. */\n.ui-screen-hidden {\n\tdisplay: none !important;\n}\n/* Transitions originally inspired by those from jQtouch, nice work, folks */\n.ui-mobile-viewport-transitioning,\n.ui-mobile-viewport-transitioning .ui-page {\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n.ui-page-pre-in {\n\topacity: 0;\n}\n.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.out {\n\t-webkit-animation-timing-function: ease-in;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-timing-function: ease-in;\n\t-moz-animation-duration: 225ms;\n\tanimation-timing-function: ease-in;\n\tanimation-duration: 225ms;\n}\n@-webkit-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-moz-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-webkit-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@-moz-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n.fade.out {\n\topacity: 0;\n\t-webkit-animation-duration: 125ms;\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-duration: 125ms;\n\t-moz-animation-name: fadeout;\n\tanimation-duration: 125ms;\n\tanimation-name: fadeout;\n}\n.fade.in {\n\topacity: 1;\n\t-webkit-animation-duration: 225ms;\n\t-webkit-animation-name: fadein;\n\t-moz-animation-duration: 225ms;\n\t-moz-animation-name: fadein;\n\tanimation-duration: 225ms;\n\tanimation-name: fadein;\n}\n.pop {\n\t-webkit-transform-origin: 50% 50%;\n\t-moz-transform-origin: 50% 50%;\n\ttransform-origin: 50% 50%;\n}\n.pop.in {\n\t-webkit-transform: scale(1);\n\t-webkit-animation-name: popin;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: scale(1);\n\t-moz-animation-name: popin;\n\t-moz-animation-duration: 350ms;\n\ttransform: scale(1);\n\tanimation-name: popin;\n\tanimation-duration: 350ms;\n    opacity: 1;\n}\n.pop.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n\topacity: 0;\n}\n.pop.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n\tanimation-name: fadein;\n}\n.pop.out.reverse {\n\t-webkit-transform: scale(.8);\n\t-webkit-animation-name: popout;\n\t-moz-transform: scale(.8);\n\t-moz-animation-name: popout;\n\ttransform: scale(.8);\n\tanimation-name: popout;\n}\n@-webkit-keyframes popin {\n    from {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n}\n@-moz-keyframes popin {\n    from {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n}\n@keyframes popin {\n    from {\n        transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        transform: scale(1);\n        opacity: 1;\n    }\n}\n@-webkit-keyframes popout {\n    from {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@-moz-keyframes popout {\n    from {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@keyframes popout {\n    from {\n        transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        transform: scale(.8);\n        opacity: 0;\n    }\n}\n/* keyframes for slidein from sides */\n@-webkit-keyframes slideinfromright {\n    from { -webkit-transform: translate3d(100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromright {\n    from { -moz-transform: translateX(100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromright {\n    from { transform: translateX(100%); }\n    to { transform: translateX(0); }\n}\n@-webkit-keyframes slideinfromleft {\n    from { -webkit-transform: translate3d(-100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromleft {\n    from { -moz-transform: translateX(-100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromleft {\n    from { transform: translateX(-100%); }\n    to { transform: translateX(0); }\n}\n/* keyframes for slideout to sides */\n@-webkit-keyframes slideouttoleft {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(-100%,0,0); }\n}\n@-moz-keyframes slideouttoleft {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(-100%); }\n}\n@keyframes slideouttoleft {\n    from { transform: translateX(0); }\n    to { transform: translateX(-100%); }\n}\n@-webkit-keyframes slideouttoright {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(100%,0,0); }\n}\n@-moz-keyframes slideouttoright {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(100%); }\n}\n@keyframes slideouttoright {\n    from { transform: translateX(0); }\n    to { transform: translateX(100%); }\n}\n.slide.out, .slide.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.slide.out {\n\t-webkit-transform: translate3d(-100%,0,0);\n\t-webkit-animation-name: slideouttoleft;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n}\n.slide.in {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromright;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromright;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromright;\n}\n.slide.out.reverse {\n\t-webkit-transform: translate3d(100%,0,0);\n\t-webkit-animation-name: slideouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n}\n.slide.in.reverse {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromleft;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromleft;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromleft;\n}\n.slidefade.out {\n\t-webkit-transform: translateX(-100%);\n\t-webkit-animation-name: slideouttoleft;\n\t-webkit-animation-duration: 225ms;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\t-moz-animation-duration: 225ms;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n\tanimation-duration: 225ms;\n}\n.slidefade.in {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n.slidefade.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: slideouttoright;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n\tanimation-duration: 200ms;\n}\n.slidefade.in.reverse {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n/* slide down */\n.slidedown.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slidedown.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfromtop;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfromtop;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfromtop;\n\tanimation-duration: 250ms;\n}\n.slidedown.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slidedown.out.reverse {\n\t-webkit-transform: translateY(-100%);\n\t-webkit-animation-name: slideouttotop;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(-100%);\n\t-moz-animation-name: slideouttotop;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(-100%);\n\tanimation-name: slideouttotop;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfromtop {\n    from { -webkit-transform: translateY(-100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfromtop {\n    from { -moz-transform: translateY(-100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfromtop {\n    from { transform: translateY(-100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttotop {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(-100%); }\n}\n@-moz-keyframes slideouttotop {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(-100%); }\n}\n@keyframes slideouttotop {\n    from { transform: translateY(0); }\n    to { transform: translateY(-100%); }\n}\n/* slide up */\n.slideup.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slideup.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfrombottom;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfrombottom;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfrombottom;\n\tanimation-duration: 250ms;\n}\n.slideup.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slideup.out.reverse {\n\t-webkit-transform: translateY(100%);\n\t-webkit-animation-name: slideouttobottom;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(100%);\n\t-moz-animation-name: slideouttobottom;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(100%);\n\tanimation-name: slideouttobottom;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfrombottom {\n    from { -webkit-transform: translateY(100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfrombottom {\n    from { -moz-transform: translateY(100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfrombottom {\n    from { transform: translateY(100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttobottom {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(100%); }\n}\n@-moz-keyframes slideouttobottom {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(100%); }\n}\n@keyframes slideouttobottom {\n    from { transform: translateY(0); }\n    to { transform: translateY(100%); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-flip {\n\t-webkit-perspective: 1000;\n\t-moz-perspective: 1000;\n\tperspective: 1000;\n\tposition: absolute;\n}\n.flip {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\tbackface-visibility: hidden;\n\ttransform: translateX(0);\n}\n.flip.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 175ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 175ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 175ms;\n}\n.flip.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 225ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 225ms;\n}\n.flip.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.flip.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-turn {\n\t-webkit-perspective: 200px;\n\t-moz-perspective: 200px;\n\t-ms-perspective: 200px;\n\tperspective: 200px;\n\tposition: absolute;\n}\n.turn {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-webkit-transform-origin: 0;\n\t\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\t-moz-transform-origin: 0;\n\t\n\tbackface-visibility :hidden;\n\ttransform: translateX(0);\n\ttransform-origin: 0;\n}\n.turn.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 125ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 125ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 125ms;\n}\n.turn.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 250ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 250ms;\n\t\n}\n.turn.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.turn.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* flow transition */\n.flow {\n\t-webkit-transform-origin: 50% 30%;\n\t-webkit-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\t-moz-transform-origin: 50% 30%;\t\n\t-moz-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\ttransform-origin: 50% 30%;\t\n\tbox-shadow: 0 0 20px rgba(0,0,0,.4);\n}\n.ui-dialog.flow {\n\t-webkit-transform-origin: none;\n\t-webkit-box-shadow: none;\n\t-moz-transform-origin: none;\t\n\t-moz-box-shadow: none;\n\ttransform-origin: none;\t\n\tbox-shadow: none;\n}\n.flow.out {\n\t-webkit-transform: translateX(-100%) scale(.7);\n\t-webkit-animation-name: flowouttoleft;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(-100%) scale(.7);\n\t-moz-animation-name: flowouttoleft;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(-100%) scale(.7);\n\tanimation-name: flowouttoleft;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.in {\n\t-webkit-transform: translateX(0) scale(1);\n\t-webkit-animation-name: flowinfromright;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(0) scale(1);\n\t-moz-animation-name: flowinfromright;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(0) scale(1);\n\tanimation-name: flowinfromright;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: flowouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: flowouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: flowouttoright;\n}\n.flow.in.reverse {\n\t-webkit-animation-name: flowinfromleft;\n\t-moz-animation-name: flowinfromleft;\n\tanimation-name: flowinfromleft;\n}\n@-webkit-keyframes flowouttoleft {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(-100%) scale(.7); }\n}\n@-moz-keyframes flowouttoleft {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(-100%) scale(.7); }\n}\n@keyframes flowouttoleft {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(-100%) scale(.7); }\n}\n@-webkit-keyframes flowouttoright {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform:  translateX(100%) scale(.7); }\n}\n@-moz-keyframes flowouttoright {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(100%) scale(.7); }\n}\n@keyframes flowouttoright {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(100%) scale(.7); }\n}\n@-webkit-keyframes flowinfromleft {\n    0% { -webkit-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromleft {\n    0% { -moz-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromleft {\n    0% { transform: translateX(-100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n@-webkit-keyframes flowinfromright {\n    0% { -webkit-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromright {\n    0% { -moz-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromright {\n    0% { transform: translateX(100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n.ui-field-contain,\n.ui-mobile fieldset.ui-field-contain {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n\tclear: both;\n\tpadding: .8em 0;\n}\n.ui-field-contain > label ~ [class*=\"ui-\"],\n.ui-field-contain .ui-controlgroup-controls {\n\tmargin: 0;\n}\n.ui-field-contain:last-child {\n\tborder-bottom-width: 0;\n}\n@media (min-width: 28em) {\n\t.ui-field-contain,\n\t.ui-mobile fieldset.ui-field-contain {\n\t\tpadding: 0;\n\t\tmargin: 1em 0;\n\t\tborder-bottom-width: 0;\n\t}\n\t.ui-field-contain:before,\n\t.ui-field-contain:after {\n\t\tcontent: \"\";\n\t\tdisplay: table;\n\t}\n\t.ui-field-contain:after {\n\t\tclear: both;\n\t}\n\t.ui-field-contain > label,\n\t.ui-field-contain .ui-controlgroup-label,\n\t.ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: left;\n\t\twidth: 20%;\n\t\tmargin: .5em 2% 0 0;\n\t}\n\t.ui-popup .ui-field-contain > label,\n\t.ui-popup .ui-field-contain .ui-controlgroup-label,\n\t.ui-popup .ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: none;\n\t\twidth: auto;\n\t\tmargin: 0 0 .4em;\n\t}\n\t.ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: left;\n\t\twidth: 78%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t}\n\t/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n\t.ui-hide-label > label ~ [class*=\"ui-\"],\n\t.ui-hide-label .ui-controlgroup-controls,\n\t.ui-popup .ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-popup .ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: none;\n\t\twidth: 100%;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline {\n\t\twidth: auto;\n\t\tmargin-right: .625em;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline.ui-btn-icon-notext {\n\t\twidth: 1.75em;\n\t}\n}\n/* content configurations. */\n.ui-grid-a,\n.ui-grid-b,\n.ui-grid-c,\n.ui-grid-d,\n.ui-grid-solo {\n\toverflow: hidden;\n}\n.ui-block-a,\n.ui-block-b,\n.ui-block-c,\n.ui-block-d,\n.ui-block-e {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfloat: left;\n\tmin-height: 1px;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n/* force new row */\n.ui-block-a {\n\tclear: left;\n}\nul.ui-grid-a,\nul.ui-grid-b,\nul.ui-grid-c,\nul.ui-grid-d,\nul.ui-grid-solo,\nli.ui-block-a,\nli.ui-block-b,\nli.ui-block-c,\nli.ui-block-d,\nli.ui-block-e {\n\tmargin-left: 0;\n\tmargin-right: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n/* No margin in grids for 100% width button elements until we can use max-width: fill-available; */\n[class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: 0;\n\tmargin-left: 0;\n}\n[class*=\"ui-block-\"] > .ui-btn,\n[class*=\"ui-block-\"] > .ui-select,\n[class*=\"ui-block-\"] > .ui-checkbox,\n[class*=\"ui-block-\"] > .ui-radio,\n[class*=\"ui-block-\"] > button.ui-btn-inline,\n[class*=\"ui-block-\"] > button.ui-btn-icon-notext,\n.ui-header [class*=\"ui-block-\"] > button.ui-btn,\n.ui-footer [class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: .3125em;\n\tmargin-left: .3125em;\n}\n.ui-grid-a > .ui-block-a,\n.ui-grid-a > .ui-block-b {\n\t/* width: 49.95%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 50%;\n}\n.ui-grid-b > .ui-block-a,\n.ui-grid-b > .ui-block-b,\n.ui-grid-b > .ui-block-c {\n\t/* width: 33.25%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 33.333%;\n}\n.ui-grid-c > .ui-block-a,\n.ui-grid-c > .ui-block-b,\n.ui-grid-c > .ui-block-c,\n.ui-grid-c > .ui-block-d {\n\t/* width: 24.925%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 25%;\n}\n.ui-grid-d > .ui-block-a,\n.ui-grid-d > .ui-block-b,\n.ui-grid-d > .ui-block-c,\n.ui-grid-d > .ui-block-d,\n.ui-grid-d > .ui-block-e {\n\t/* width: 19.925%; IE7 */\n\twidth: 20%;\n}\n.ui-grid-solo > .ui-block-a {\n\twidth: 100%;\n\tfloat: none; \n}\n/* preset breakpoint to switch to stacked grid styles below 35em (560px) */\n@media (max-width: 35em) {\n\t.ui-responsive > .ui-block-a,\n\t.ui-responsive > .ui-block-b,\n\t.ui-responsive > .ui-block-c,\n\t.ui-responsive > .ui-block-d,\n\t.ui-responsive > .ui-block-e {\n\t\twidth: 100%; \n\t\tfloat: none; \n\t}\n}\n/* fixed page header & footer configuration */\n.ui-header-fixed,\n.ui-footer-fixed {\n\tleft: 0;\n\tright: 0;\n\twidth: 100%;\n\tposition: fixed;\n\tz-index: 1000;\n}\n.ui-header-fixed {\n\ttop: -1px;\n\tpadding-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden {\n\ttop: 0;\n\tpadding-top: 0;\n}\n.ui-header-fixed .ui-btn-left,\n.ui-header-fixed .ui-btn-right {\n\tmargin-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden .ui-btn-left,\n.ui-header-fixed.ui-fixed-hidden .ui-btn-right {\n\tmargin-top: 0;\n}\n.ui-footer-fixed {\n\tbottom: -1px;\n\tpadding-bottom: 1px;\n}\n.ui-footer-fixed.ui-fixed-hidden {\n\tbottom: 0;\n\tpadding-bottom: 0;\n}\n.ui-header-fullscreen,\n.ui-footer-fullscreen {\n\tfilter: Alpha(Opacity=90);\n\topacity: .9;\n}\n/* updatePagePadding() will update the padding to actual height of header and footer. */\n.ui-page-header-fixed {\n\tpadding-top: 2.8125em;\n}\n.ui-page-footer-fixed {\n\tpadding-bottom: 2.8125em;\n}\n.ui-page-header-fullscreen > .ui-content,\n.ui-page-footer-fullscreen > .ui-content {\n\tpadding: 0;\n}\n.ui-fixed-hidden {\n\tposition: absolute;\n}\n/* Tap toggle: hide external fixed footer. See issue #6604 */\n.ui-footer-fixed.ui-fixed-hidden {\n  display: none;\n}\n.ui-page .ui-footer-fixed.ui-fixed-hidden {\n  display: block\n}\n.ui-page-header-fullscreen .ui-fixed-hidden,\n.ui-page-footer-fullscreen .ui-fixed-hidden {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-header-fixed .ui-btn,\n.ui-footer-fixed .ui-btn { \n\tz-index: 10;\n}\n/* workarounds for other widgets */\n.ui-android-2x-fixed .ui-li-has-thumb {\n\t-webkit-transform: translate3d(0,0,0);\n}\n.ui-navbar {\n\tmax-width: 100%;\n}\n.ui-navbar ul:before,\n.ui-navbar ul:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-navbar ul:after {\n\tclear: both;\n}\n.ui-navbar ul {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n\tdisplay: block;\n\tborder: 0;\n\tmax-width: 100%;\n\toverflow: visible;\n}\n.ui-navbar li .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: block;\n\tmargin: 0;\n\tborder-right-width: 0;\n}\n.ui-header .ui-navbar li button.ui-btn,\n.ui-footer .ui-navbar li button.ui-btn {\n\tmargin: 0;\n\twidth: 100%;\n}\n.ui-navbar .ui-btn:focus {\n\tz-index: 1;\n}\n/* fixes gaps caused by subpixel problem */\n.ui-navbar li:last-child .ui-btn {\n\tmargin-right: -4px;\n}\n.ui-navbar li:last-child .ui-btn:after {\n\tmargin-right: 4px;\n}\n.ui-content .ui-navbar li:last-child .ui-btn,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: 0;\n}\n.ui-content .ui-navbar li:last-child .ui-btn:after,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after {\n\tmargin-right: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after {\n\tmargin-right: 1px;\n}\n.ui-navbar .ui-grid-duo .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-header .ui-navbar .ui-btn,\n.ui-footer .ui-navbar .ui-btn {\n\tborder-top-width: 0;\n\tborder-bottom-width: 0;\n}\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-header .ui-title ~ .ui-navbar .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n/* Hide the native input element */\n.ui-input-btn input {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tbackground: #fff;\n\tbackground: rgba(255,255,255,0);\n\tfilter: Alpha(Opacity=0);\n\topacity: .1;\n\tfont-size: 1px;\n\ttext-indent: -9999px;\n\tz-index: 2;\n}\n/* Fixes IE/WP filter alpha opacity bugs */\n.ui-input-btn.ui-state-disabled input {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible {\n\tmargin: 0 -1em;\n}\n.ui-collapsible-inset,\n.ui-collapsible-set {\n\tmargin: .5em 0;\n}\n.ui-collapsible-heading {\n\tdisplay: block;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n}\n.ui-collapsible-heading .ui-btn {\n\ttext-align: left;\n\tmargin: 0;\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n}\n.ui-collapsible-heading .ui-btn-icon-top,\n.ui-collapsible-heading .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-collapsible-inset .ui-collapsible-heading .ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-collapsible-collapsed + .ui-collapsible:not(.ui-collapsible-inset) > .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-collapsible-heading-status {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible-content {\n\tdisplay: block;\n\tmargin: 0;\t\n\tpadding: .5em 1em;\n}\n.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n\tborder-top-width: 0;\n\tborder-bottom-width: 1px;\n\tborder-style: solid;\n}\n.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 1px;\n\tborder-right-width: 1px;\n}\n.ui-collapsible-inset .ui-collapsible-content {\n\tmargin: 0;\n}\n.ui-collapsible-content-collapsed {\n\tdisplay: none;\n}\n.ui-collapsible-set > .ui-collapsible.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-collapsible-heading,\n.ui-collapsible-heading > .ui-btn {\n\t-webkit-border-radius: inherit;\t\n\tborder-radius: inherit;\t\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\t\n\tborder-top-left-radius: inherit;\t\t\n}\n.ui-collapsible-content,\n.ui-collapsible-set .ui-collapsible.ui-last-child {\n\t-webkit-border-bottom-right-radius: inherit;\t\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\t\n\tborder-bottom-left-radius: inherit;\t\t\n}\n.ui-collapsible-themed-content:not(.ui-collapsible-collapsed) > .ui-collapsible-heading {\n\t-webkit-border-bottom-right-radius: 0;\t\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\t\n\tborder-bottom-left-radius: 0;\t\t\n}\n.ui-collapsible-set .ui-collapsible {\n\tmargin: -1px -1em 0;\n}\n.ui-collapsible-set .ui-collapsible-inset {\n\tmargin: -1px 0 0;\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\tmargin-top: 0;\n}\n.ui-controlgroup,\nfieldset.ui-controlgroup {\n\tpadding: 0;\n\tmargin: .5em 0;\n}\n.ui-field-contain .ui-controlgroup,\n.ui-field-contain fieldset.ui-controlgroup {\n\tmargin: 0;\n}\n.ui-mini .ui-controlgroup-label {\n\tfont-size: 16px;\n}\n.ui-controlgroup.ui-mini .ui-btn-icon-notext,\n.ui-controlgroup .ui-mini.ui-btn-icon-notext {\n\tfont-size: inherit;\n}\n.ui-controlgroup-controls .ui-btn,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-select {\n\tmargin: 0;\n}\n.ui-controlgroup-controls .ui-btn:focus,\n.ui-controlgroup-controls .ui-btn.ui-focus {\n\tz-index: 1;\n}\n.ui-controlgroup-controls li {\n\tlist-style: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:before,\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tclear: both;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls li > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select {\n\tfloat: left;\n\tclear: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,\n.ui-controlgroup-controls .ui-btn-icon-notext {\n\twidth: auto;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext {\n\twidth: 1.5em;\n}\n .ui-controlgroup-controls .ui-btn-icon-notext {\n\theight: auto;\n\tpadding: .7em 1em;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-bottom-width: 1px;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn {\n\tborder-right-width: 0;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-right-width: 1px;\n}\n.ui-controlgroup-controls .ui-btn-corner-all,\n.ui-controlgroup-controls .ui-btn.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-controlgroup-controls,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-select,\n.ui-controlgroup-controls li {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-last-child {\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-controls a.ui-shadow:not(:focus),\n.ui-controlgroup-controls button.ui-shadow:not(:focus),\n.ui-controlgroup-controls div.ui-shadow:not(.ui-focus) {\n\t-moz-box-shadow: none;\n\t-webkit-box-shadow: none;\n\tbox-shadow: none;\n}\n/* Fixes legend not wrapping on IE10 */\n.ui-controlgroup-label legend {\n\tmax-width: 100%;\n}\n.ui-controlgroup-controls > label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-dialog {\n\t background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */\n}\n.ui-dialog-contain {\n\twidth: 92.5%;\n\tmax-width: 500px;\n\tmargin: 10% auto 1em auto;\n\tpadding: 0;\n\tposition: relative;\n\ttop: -1em;\n}\n.ui-dialog-contain > .ui-header, \n.ui-dialog-contain > .ui-content, \n.ui-dialog-contain > .ui-footer { \n\tdisplay: block;\n\tposition: relative; \n\twidth: auto;\n\tmargin: 0;\n}\n.ui-dialog-contain > .ui-header {\n\toverflow: hidden;\n\tz-index: 10; \n\tpadding: 0;\n\tborder-top-width: 0;\n}\n.ui-dialog-contain > .ui-footer {\n\tz-index: 10; \n\tpadding: 0 1em; \n\tborder-bottom-width: 0;\n}\n.ui-popup-open .ui-header-fixed,\n.ui-popup-open .ui-footer-fixed {\n\tposition: absolute !important; /* See issues #4816, #4844 and #4874 and popup.js */\n}\n.ui-popup-screen {\n\tbackground-image: url(\"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\"); /* Necessary to set some form of background to ensure element is clickable in IE6/7. While legacy IE won't understand the data-URI'd image, it ensures no additional requests occur in all other browsers with little overhead. */\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 1px;\n\tposition: absolute;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 1099;\n}\n.ui-popup-screen.in {\n\topacity: 0.5;\n\tfilter: Alpha(Opacity=50);\n}\n.ui-popup-screen.out {\n\topacity: 0;\n\tfilter: Alpha(Opacity=0);\n}\n.ui-popup-container {\n\tz-index: 1100;\n\tdisplay: inline-block;\n\tposition: absolute;\n\tpadding: 0;\n\toutline: 0;\n}\n.ui-popup {\n\tposition: relative;\n}\n.ui-popup.ui-body-inherit {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-hidden {\n\tleft: 0;\n\ttop: 0;\n\tposition: absolute !important;\n\tvisibility: hidden;\n}\n.ui-popup-truncate {\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-popup.ui-content,\n.ui-popup .ui-content {\n\toverflow: visible;\n}\n.ui-popup > .ui-header {\n\tborder-top-width: 0;\n}\n.ui-popup > .ui-footer {\n\tborder-bottom-width: 0;\n}\n.ui-popup > p,\n.ui-popup > h1,\n.ui-popup > h2,\n.ui-popup > h3,\n.ui-popup > h4,\n.ui-popup > h5,\n.ui-popup > h6 {\n\tmargin: .5em .4375em;\n}\n.ui-popup > span {\n\tdisplay: block;\n\tmargin: .5em .4375em;\n}\n.ui-popup-container .ui-content > p,\n.ui-popup-container .ui-content > h1,\n.ui-popup-container .ui-content > h2,\n.ui-popup-container .ui-content > h3,\n.ui-popup-container .ui-content > h4,\n.ui-popup-container .ui-content > h5,\n.ui-popup-container .ui-content > h6 {\n\tmargin: .5em 0;\n}\n.ui-popup-container .ui-content > span {\n\tmargin: 0;\n}\n.ui-popup-container .ui-content > p:first-child,\n.ui-popup-container .ui-content > h1:first-child,\n.ui-popup-container .ui-content > h2:first-child,\n.ui-popup-container .ui-content > h3:first-child,\n.ui-popup-container .ui-content > h4:first-child,\n.ui-popup-container .ui-content > h5:first-child,\n.ui-popup-container .ui-content > h6:first-child {\n\tmargin-top: 0;\n}\n.ui-popup-container .ui-content > p:last-child,\n.ui-popup-container .ui-content > h1:last-child,\n.ui-popup-container .ui-content > h2:last-child,\n.ui-popup-container .ui-content > h3:last-child,\n.ui-popup-container .ui-content > h4:last-child,\n.ui-popup-container .ui-content > h5:last-child,\n.ui-popup-container .ui-content > h6:last-child {\n\tmargin-bottom: 0;\n}\n.ui-popup > img {\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tvertical-align: middle;\n}\n.ui-popup:not(.ui-content) > img:only-child,\n.ui-popup:not(.ui-content) > .ui-btn-left:first-child + img:last-child,\n.ui-popup:not(.ui-content) > .ui-btn-right:first-child + img:last-child {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-popup iframe {\n\tvertical-align: middle;\n}\n.ui-popup > .ui-btn-left,\n.ui-popup > .ui-btn-right {\n\tposition: absolute; \n\ttop: -11px;\n\tmargin: 0;\n\tz-index: 1101;\n}\n.ui-popup > .ui-btn-left {\n\tleft: -11px;\n}\n.ui-popup > .ui-btn-right {\n\tright: -11px;\n}\n/* Dimensions related to the popup arrow\n-----------------------------------------------------------------------------------------------------------*/\n/* desired triangle height: 10px */\n/**\n * guide for the arrow - its width, height, and offset are theme-dependent and\n * should be expessed as left, right, top, bottom, so that the element bearing\n * such a class becomes stretched inside its parent position: relative element.\n * The left/top/right/bottom specified below should reflect the corresponding\n * border radii and so it leaves room for the shadow:\n *     ..--------------------..\n *   .\"        ^ top           \".\n *  /          v                 \\\n * |     +------------------+     |\n * |     |                  |     |\n * | left|                  |right|\n * |<--->|                  |<--->|\n * |     +------------------+     |\n *  \\          ^                 /\n *   `.        v bottom        .'\n *     \"\"--------------------\"\"\n * The idea is that the top/left of the arrow container box does not move to a\n * coordinate smaller than the top/left of the guide and the right/bottom of\n * the arrow container box does not move to a coordinate larger than the\n * bottom/right of the guide. This will help us avoid the following situation:\n *        ..--------------------..\n *      .\"        ^ top           \".\n *   /|/          v                 \\\n *  / |     +------------------+     |\n *  \\ |     |                  |     |\n *   \\| left|                  |right|\n *    |<--->|                  |<--->|\n *    |     +------------------+     |\n *     \\          ^                 /\n *      `.        v bottom        .'\n *        \"\"--------------------\"\"\n * The arrow should not receive a top/left coordinate such that it is too close\n * to one of the corners, because then at first the shadow of the arrow and,\n * given a coordinate even closer to the corner, even the body of the arrow will\n * \"stick out\" of the corner of the popup. The guide provides a hint to the\n * arrow positioning code as to which range of values is acceptable for the\n * arrow container's top/left coordinate.\n **/\n.ui-popup-arrow-container {\n\twidth: 20px;\n\theight: 20px;\n}\n/* aside from the \"infinities\" (-1000,2000), triangle height is used */\n.ui-popup-arrow-container.ui-popup-arrow-l {\n\tleft: -10px;\n\tclip: rect(-1000px,10px,2000px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-t {\n\ttop: -10px;\n\tclip: rect(-1000px,2000px,10px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-r {\n\tright: -10px;\n\tclip: rect(-1000px,2000px,2000px,10px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-b {\n\tbottom: -10px;\n\tclip: rect(10px,2000px,1000px,-1000px);\n}\n/**\n * For each side, the arrow is twice the desired size and its corner is aligned\n * with the edge of the container:\n *                                           \n *           /\\         /\\                +----+       /\\\n *          /  \\       /  \\               | /\\ |top   /  \\\n *      +----+  \\     /  +----+       +-->|/  \\|     /    \\\n *  left| /  |   \\   /   |  \\ |right  |   |    |    /      \\\n *      |/   |    \\ /    |   \\|       |  /|    |\\  /        \\\n *      |\\   |    / \\    |   /|       | / +----+ \\ \\ +----+ /\n *      | \\  |   /   \\   |  / |       | \\        /  \\|    |/\n *      +----+  /     \\  +----+       |  \\      /    |    |\n *       ^  \\  /       \\  /  ^        |   \\    /  +->|\\  /|\n *       |   \\/         \\/   |        |    \\  /   |  | \\/ |bottom\n *       |                   |        |     \\/    |  +----+\n *       +-------------------+--------+-----------+\n *                           |\n *                    arrow container\n *                     (clips arrow)\n **/\n.ui-popup-arrow-container .ui-popup-arrow {\n\t/* (4*desired triangle height)/sqrt(2) - does not account for border - centred within the outer rectangle */\n\twidth: 28.284271247px;\n\theight: 28.284271247px;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: 5.857864376px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: -14.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow {\n\tleft: 5.857864376px;\n\ttop: -4.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow {\n\tleft: -14.142135623px;\n\ttop: -4.142135623px;\n}\n/* Fix rotation center for oldIE - see http://www.useragentman.com/IETransformsTranslator/ */\n.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -7.0710678118654755px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -4.142135623730951px;\n}\n \n.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow {\n    margin-left: -7.0710678118654755px;\n    margin-top: -5.857864376269049px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow {\n    margin-left: -4.142135623730951px;\n    margin-top: -5.857864376269049px;\n}\n/* structure */\n.ui-popup > .ui-popup-arrow-guide {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tvisibility: hidden;\n}\n.ui-popup-arrow-container {\n\tposition: absolute;\n}\n.ui-popup-arrow {\n\t-webkit-transform: rotate(45deg);\n\t-moz-transform: rotate(45deg);\n\t-ms-transform: rotate(45deg);\n\ttransform: rotate(45deg);\n\tposition: absolute;\n\toverflow: hidden;\n\tbox-sizing: border-box;\n}\n.ui-popup-arrow-container.ie .ui-popup-arrow {\n\t-ms-filter: \"progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod='auto expand')\";\n\tfilter: progid:DXImageTransform.Microsoft.Matrix(\n\t      \tM11=0.7071067811865474,\n        \tM12=-0.7071067811865477,\n        \tM21=0.7071067811865477,\n        \tM22=0.7071067811865474,\n        \tSizingMethod='auto expand');\n}\n.ui-checkbox,\n.ui-radio {\n\tmargin: .5em 0;\n\tposition: relative;\n}\n.ui-checkbox .ui-btn,\n.ui-radio .ui-btn {\n\tmargin: 0;\n\ttext-align: left;\n\twhite-space: normal; /* Nowrap + ellipsis doesn't work on label. Issue #1419. */\n\tz-index: 2;\n}\n.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,\n.ui-controlgroup .ui-radio .ui-btn.ui-focus {\n\tz-index: 3;\n}\n.ui-checkbox .ui-btn-icon-top,\n.ui-radio .ui-btn-icon-top,\n.ui-checkbox .ui-btn-icon-bottom,\n.ui-radio .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,\n.ui-controlgroup-horizontal .ui-radio .ui-btn:after {\n\tcontent: none;\n\tdisplay: none;\n}\n/* Native input positioning */\n.ui-checkbox input,\n.ui-radio input {\n\tposition: absolute;\n\tleft: .466em;\n\ttop: 50%;\n\twidth: 22px;\n\theight: 22px;\n\tmargin: -11px 0 0 0;\n\toutline: 0 !important;\n\tz-index: 1;\n}\n.ui-controlgroup-horizontal .ui-checkbox input,\n.ui-controlgroup-horizontal .ui-radio input {\n\tleft: 50%;\n\tmargin-left: -9px;\n}\n.ui-checkbox input:disabled,\n.ui-radio input:disabled {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select {\n\tmargin-top: .5em;\n\tmargin-bottom: .5em; /* no shorthand for margin because it would override margin-right for inline selects */\n\tposition: relative;\n}\n.ui-select > select {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select .ui-btn {\n\tmargin: 0;\n\topacity: 1; /* Fixes #2588: When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select (including \"inherit\") without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */\n}\n.ui-select .ui-btn select {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 1.5em;\n\tmin-height: 100%;\n\theight: 3em;\n\tmax-height: 100%;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 2;\n}\n@-moz-document url-prefix() {\n\t.ui-select .ui-btn select {\n\t\topacity: 0.0001;\n\t}\n}\n/* Display none because of issues with IE/WP's filter alpha opacity */\n.ui-select .ui-state-disabled select {\n\tdisplay: none;\n}\n/* Because we add all classes of the select and option elements to the span... */ \n.ui-select span.ui-state-disabled {\n\tfilter: Alpha(Opacity=100);\n\topacity: 1;\n}\n.ui-select .ui-btn.ui-select-nativeonly {\n\tborder-radius: 0;\n\tborder: 0;\n}\n.ui-select .ui-btn.ui-select-nativeonly select {\n\topacity: 1;\n\ttext-indent: 0;\n\tdisplay: block;\n}\n/* ui-li-count is styled in the listview CSS. We set padding and offset here because select supports icon position while listview doesn't. */\n.ui-select .ui-li-has-count.ui-btn {\n\tpadding-right: 2.8125em;\n}\n.ui-select .ui-li-has-count.ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-select .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n/* We set the rules for the span as well to fix an issue on Chrome with text-overflow ellipsis for the button in combination with text-align center. */\n.ui-select .ui-btn > span:not(.ui-li-count) {\n\tdisplay: block;\n\ttext-overflow: ellipsis;\n\toverflow: hidden !important;\n\twhite-space: nowrap;\n}\n.ui-selectmenu.ui-popup {\n\tmin-width: 11em;\n}\n.ui-selectmenu .ui-dialog-contain {\n\toverflow: hidden;\n}\n.ui-selectmenu .ui-header {\n\tmargin: 0;\n\tpadding: 0;\n\tborder-width: 0;\n}\n.ui-selectmenu.ui-dialog .ui-header {\n\tz-index: 1;\n\tposition: relative;\n}\n.ui-selectmenu.ui-popup .ui-header {\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n}\n/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button.  this shim's content in there */\n.ui-selectmenu.ui-popup .ui-header h1:after {\n\tcontent: '.';\n\tvisibility: hidden;\n}\n.ui-selectmenu .ui-header .ui-title {\n\tmargin: 0 2.875em;\n}\n.ui-selectmenu.ui-dialog .ui-content {\n\toverflow: visible;\n\tz-index: 1;\n}\n.ui-selectmenu .ui-selectmenu-list {\n\tmargin: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-header:not(.ui-screen-hidden) + .ui-selectmenu-list {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-top-left-radius: 0;\n\tborder-top-left-radius: 0;\n}\n.ui-header.ui-screen-hidden + .ui-selectmenu-list li.ui-first-child .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-selectmenu .ui-btn.ui-li-divider {\n\tcursor: default;\n}\n.ui-selectmenu .ui-selectmenu-placeholder {\n\tdisplay: none;\n}\n.ui-listview,\n.ui-listview > li {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n.ui-content .ui-listview,\n.ui-panel-inner > .ui-listview {\n\tmargin: -1em;\n}\n.ui-content .ui-listview-inset,\n.ui-panel-inner > .ui-listview-inset {\n\tmargin: 1em 0;\n}\n.ui-collapsible-content > .ui-listview {\n\tmargin: -.5em -1em;\n}\n.ui-collapsible-content > .ui-listview-inset {\n\tmargin: .5em 0;\n}\n.ui-listview > li {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tmargin: 0;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: left;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li > .ui-btn:focus {\n\tz-index: 1;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tborder-width: 1px 0 0 0;\n\tborder-style: solid;\n}\n.ui-listview-inset > .ui-li-static,\n.ui-listview-inset > .ui-li-divider,\n.ui-listview-inset > li > a.ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-listview > .ui-li-static.ui-last-child,\n.ui-listview > .ui-li-divider.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 1px;\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child,\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-listview > li.ui-first-child,\n.ui-listview > li.ui-first-child > a.ui-btn {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n}\n.ui-listview > li.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-listview > li.ui-li-has-alt > a.ui-btn {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n.ui-listview > li.ui-first-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-top-left-radius: 0;\t\n\tborder-top-left-radius: 0;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-listview > li.ui-last-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-listview > li.ui-first-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\t\n}\n.ui-listview > li.ui-last-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\t\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-listview > .ui-li-static {\n\tpadding: .7em 1em;\n}\n.ui-listview > .ui-li-divider {\n\tpadding: .5em 1.143em;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tcursor: default;\n\toutline: 0; /* Dividers in custom selectmenus have tabindex */\n}\n.ui-listview > .ui-li-has-count > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-count,\n.ui-listview > .ui-li-divider.ui-li-has-count {\n\tpadding-right: 2.8125em;\n}\n.ui-listview > .ui-li-has-count > .ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-listview > .ui-li-has-thumb > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-thumb {\n\tmin-height: 3.625em;\n\tpadding-left: 6.25em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-icon {\n\tmin-height: 1.25em;\n\tpadding-left: 2.5em;\n}\n/* Used by both listview and custom multiple select button */\n.ui-li-count {\n\tposition: absolute;\n\tfont-size: 12.5px;\n\tfont-weight: bold;\n\ttext-align: center;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tpadding: 0 .48em;\n\tline-height: 1.6em;\n\tmin-height: 1.6em;\n\tmin-width: .64em;\n\tright: .8em;\n\ttop: 50%;\n\tmargin-top: -.88em;\n}\n.ui-listview .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n.ui-listview .ui-li-has-thumb > img:first-child,\n.ui-listview .ui-li-has-thumb > .ui-btn > img:first-child,\n.ui-listview .ui-li-has-thumb .ui-li-thumb {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\tmax-height: 5em;\n\tmax-width: 5em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > img:first-child,\n.ui-listview > .ui-li-has-icon > .ui-btn > img:first-child {\n\tposition: absolute;\n\tleft: .625em;\n\ttop: .9em;\n\tmax-height: 1em;\n\tmax-width: 1em;\n}\n.ui-listview > li h1,\n.ui-listview > li h2,\n.ui-listview > li h3,\n.ui-listview > li h4,\n.ui-listview > li h5,\n.ui-listview > li h6 {\n\tfont-size: 1em;\n\tfont-weight: bold;\n\tdisplay: block;\n\tmargin: .45em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li p {\n\tfont-size: .75em;\n\tfont-weight: normal;\n\tdisplay: block;\n\tmargin: .6em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview .ui-li-aside {\n\tposition: absolute;\n\ttop: 1em;\n\tright: 3.333em;\n\tmargin: 0;\n\ttext-align: right;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn {\n\tmargin-right: 2.5em;\n\tborder-right-width: 0;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tposition: absolute;\n\twidth: 2.5em;\n\theight: 100%;\n\tmin-height: auto;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-left-width: 1px;\n\ttop: 0;\n\tright: 0;\n\tmargin: 0;\n\tpadding: 0;\n\tz-index: 2;\n}\n.ui-listview-inset > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tborder-right-width: 1px;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn:focus {\n\tz-index: 3;\n}\nol.ui-listview,\nol.ui-listview > .ui-li-divider {\n\tcounter-reset: listnumbering;\n}\nol.ui-listview > li > .ui-btn,\nol.ui-listview > li.ui-li-static {\n\tvertical-align: middle;\n}\nol.ui-listview > li > .ui-btn:first-child:before,\nol.ui-listview > li.ui-li-static:before,\nol.ui-listview > li.ui-field-contain > label:before,\nol.ui-listview > li.ui-field-contain > .ui-controlgroup-label:before {\n\tdisplay: inline-block;\n\tfont-size: .9em;\n\tfont-weight: normal;\n\tpadding-right: .3em;\n\tmin-width: 1.4em;\n\tline-height: 1.5;\n\tvertical-align: middle;\n\tcounter-increment: listnumbering;\n\tcontent: counter(listnumbering) \".\";\n}\nol.ui-listview > li.ui-field-contain:before {\n\tcontent: none;\n\tdisplay: none;\n}\nol.ui-listview > li h1:first-child,\nol.ui-listview > li h2:first-child,\nol.ui-listview > li h3:first-child,\nol.ui-listview > li h4:first-child,\nol.ui-listview > li h5:first-child,\nol.ui-listview > li h6:first-child,\nol.ui-listview > li p:first-child,\nol.ui-listview > li img:first-child + * {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\nol.ui-listview > li h1:first-child ~ *,\nol.ui-listview > li h2:first-child ~ *,\nol.ui-listview > li h3:first-child ~ *,\nol.ui-listview > li h4:first-child ~ *,\nol.ui-listview > li h5:first-child ~ *,\nol.ui-listview > li h6:first-child ~ *,\nol.ui-listview > li p:first-child ~ *,\nol.ui-listview > li img:first-child + * ~ * {\n\tmargin-top: 0;\n\ttext-indent: 2.04em; /* (1.4em + .3em) * .9em / .75em */\n}\nhtml .ui-filterable + .ui-listview,\nhtml .ui-filterable.ui-listview {\n\tmargin-top: .5em;\n}\n.ui-collapsible-content > form.ui-filterable {\n\tmargin-top: -.5em;\n}\n.ui-collapsible-content > .ui-input-search.ui-filterable {\n\tmargin-top: 0;\n}\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 1px;\n}\ndiv.ui-slider {\n\theight: 30px;\n\tmargin: .5em 0;\n\tpadding: 0;\n\t-ms-touch-action: pan-y pinch-zoom double-tap-zoom;\n}\ndiv.ui-slider:before,\ndiv.ui-slider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\ndiv.ui-slider:after {\n\tclear: both;\n}\ninput.ui-slider-input {\n\tdisplay: block;\n\tfloat: left;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tmargin: 0;\n\tpadding: 4px;\n\twidth: 40px;\n\theight: 20px;\n\tline-height: 20px;\n\tborder-width: 1px;\n\tborder-style: solid;\n\toutline: 0;\n\ttext-align: center;\n\tvertical-align: text-bottom;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tappearance: none;\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-slider-input::-webkit-outer-spin-button,\n.ui-slider-input::-webkit-inner-spin-button {\n\t-webkit-appearance: none;\n\tmargin: 0;\n}\n.ui-slider-track {\n\tposition: relative;\n\toverflow: visible;\n\tborder-width: 1px;\n\tborder-style: solid;\n\theight: 15px;\n\tmargin: 0 15px 0 68px;\n\ttop: 6px;\n}\n.ui-slider-track.ui-mini {\n\theight: 12px;\n\ttop: 8px;\n}\n.ui-slider-track .ui-slider-bg {\n\theight: 100%;\n}\n/* High level of specificity to override button margins in grids */\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tposition: absolute;\n\tz-index: 1;\n\ttop: 50%;\n\twidth: 28px;\n\theight: 28px;\n\tmargin: -15px 0 0 -15px;\n\toutline: 0;\n\tpadding: 0;\n}\n.ui-slider-track.ui-mini .ui-slider-handle {\n\theight: 14px;\n\twidth: 14px;\n\tmargin: -8px 0 0 -8px;\n}\nselect.ui-slider-switch {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\ndiv.ui-slider-switch {\n\tdisplay: inline-block;\n\theight: 32px;\n\twidth: 5.8em;\n\ttop: 0;\n}\n/* reset the clearfix */\ndiv.ui-slider-switch:before,\ndiv.ui-slider-switch:after {\n\tdisplay: none;\n\tclear: none;\n}\ndiv.ui-slider-switch.ui-mini {\n\theight: 29px;\n\ttop: 0;\n}\n.ui-slider-inneroffset {\n\tmargin: 0 16px;\n\tposition: relative;\n\tz-index: 1;\n}\n.ui-slider-switch.ui-mini .ui-slider-inneroffset {\n\tmargin: 0 15px 0 14px;\n}\n.ui-slider-switch .ui-btn.ui-slider-handle {\n\tmargin: 1px 0 0 -15px;\n}\n.ui-slider-switch.ui-mini .ui-slider-handle {\n\twidth: 25px;\n\theight: 25px;\n\tmargin: 1px 0 0 -13px;\n\tpadding: 0;\n}\n.ui-slider-handle-snapping {\n\t-webkit-transition: left 70ms linear;\n\t-moz-transition: left 70ms linear;\n\ttransition: left 70ms linear;\n}\n.ui-slider-switch .ui-slider-label {\n\tposition: absolute;\n\ttext-align: center;\n\twidth: 100%;\n\toverflow: hidden;\n\tfont-size: 16px;\n\ttop: 0;\n\tline-height: 2;\n\tmin-height: 100%;\n\twhite-space: nowrap;\n\tcursor: pointer;\n}\n.ui-slider-switch.ui-mini .ui-slider-label {\n\tfont-size: 14px;\n}\n.ui-slider-switch .ui-slider-label-a {\n\tz-index: 1;\n\tleft: 0;\n\ttext-indent: -1.5em;\n}\n.ui-slider-switch .ui-slider-label-b {\n\tz-index: 0;\n\tright: 0;\n\ttext-indent: 1.5em;\n}\n/* The corner radii for ui-slider-switch/track can be specified in theme CSS. The bg and handle inherits. */\n.ui-slider-track .ui-slider-bg,\n.ui-slider-switch .ui-slider-label,\n.ui-slider-switch .ui-slider-inneroffset,\n.ui-slider-handle {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-field-contain div.ui-slider-switch {\n\tmargin: 0;\n}\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-field-contain div.ui-slider-switch,\n.ui-field-contain.ui-hide-label div.ui-slider-switch,\nhtml .ui-popup .ui-field-contain div.ui-slider-switch {\n\tdisplay: inline-block;\n\twidth: 5.8em;\n}\n/* slider tooltip\n-----------------------------------------------------------------------------------------------------------*/\n.ui-slider-popup {\n\twidth: 64px;\n\theight: 64px;\n\tfont-size: 36px;\n\tpadding-top: 14px;\n\topacity: 0.8;\n}\n.ui-slider-popup {\n\tposition: absolute !important;\n\ttext-align: center;\n\tz-index: 100;\n}\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tfont-size: .9em;\n\tline-height: 30px;\n}\n.ui-rangeslider {\n\tmargin: .5em 0;\n}\n.ui-rangeslider:before,\n.ui-rangeslider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-rangeslider:after {\n\tclear: both;\n}\n.ui-rangeslider .ui-slider-input.ui-rangeslider-last {\n\tfloat: right;\n}\n.ui-rangeslider .ui-rangeslider-sliders {\n\tposition: relative;\n\toverflow: visible;\n\theight: 30px;\n\tmargin: 0 68px;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track {\n\tposition: absolute;\n\ttop: 6px;\n\tright: 0;\n\tleft: 0;\n\tmargin: 0;\n}\n.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track {\n\ttop: 8px;\n}\n.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg {\n\tdisplay: none;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\tbackground-color: transparent;\n\tbackground: none;\n\tborder-width: 0;\n\theight: 0;\n}\n/* this makes ie6 and ie7 set height to 0 to fix z-index problem */\nhtml >/**/body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 15px;\n\tborder-width: 1px;\n}\nhtml >/**/body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 12px;\n}\n/* Hide the second label (the first is moved outside the div) */\ndiv.ui-rangeslider label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-field-contain .ui-rangeslider input.ui-slider-input,\n.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,\n.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,\n.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders {\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n}\n.ui-input-text,\n.ui-input-search {\n\tmargin: .5em 0;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-mini {\n\tmargin: .446em;\n}\n.ui-input-text input,\n.ui-input-search input,\ntextarea.ui-input-text {\n\tpadding: .4em;\n\tline-height: 1.4em;\n\tdisplay: block;\n\twidth: 100%;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\toutline: 0;\n}\n.ui-input-text input,\n.ui-input-search input {\n\tmargin: 0;\n\tmin-height: 2.2em;\n\ttext-align: left; /* Opera aligns type=\"date\" right by default */\n\tborder: 0;\n\tbackground: transparent none;\n\t-webkit-appearance: none;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\ntextarea.ui-input-text {\n\toverflow: auto;\n\tresize: vertical;\n}\n.ui-mini .ui-input-text input,\n.ui-mini .ui-input-search input,\n.ui-input-text.ui-mini input,\n.ui-input-search.ui-mini input,\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tfont-size: 14px;\n}\n/* Same margin for mini textareas as other mini sized widgets (12.5/14 * 0.5em) */\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tmargin: .446em 0;\n}\n.ui-input-has-clear,\n.ui-input-search {\n\tposition: relative;\n}\n/* Padding on the div instead of input because of browser spinners etc. */\n.ui-input-has-clear {\n\tpadding-right: 2.375em;\n}\n.ui-mini.ui-input-has-clear {\n\tpadding-right: 2.923em;\n}\n.ui-input-has-clear input {\n\tpadding-right: 0;\n\t/* Autofill on Chrome has bg color so we unset corners right as well. */\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n/* Search icon */\n.ui-input-search input {\n\tpadding-left: 1.75em;\n}\n.ui-input-search:after {\n\tposition: absolute;\n\tleft: .3125em;\n\ttop: 50%;\n\tmargin-top: -7px;\n\tcontent: \"\";\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\twidth: 14px;\n\theight: 14px;\n\tfilter: Alpha(Opacity=50);\n\topacity: .5;\n}\n.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,\n.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear {\n\tposition: absolute;\n\tright: 0;\n\ttop: 50%;\n\tmargin: -14px .3125em 0;\n\tborder: 0;\n\tbackground-color: transparent;\n}\n.ui-input-search .ui-input-clear-hidden,\n.ui-input-text .ui-input-clear-hidden {\n\tdisplay: none;\n}\n/* Resolves issue #5166: Added to support issue introduced in Firefox 15. We can likely remove this in the future. */\n.ui-input-text input::-moz-placeholder,\n.ui-input-search input::-moz-placeholder,\ntextarea.ui-input-text::-moz-placeholder {\n\tcolor: #aaa;\n}\n/* Same for IE10 */\n.ui-input-text input:-ms-input-placeholder,\n.ui-input-search input:-ms-input-placeholder,\ntextarea.ui-input-text:-ms-input-placeholder {\n\tcolor: #aaa;\n}\n/* Resolves issue #5131: Width of textinput depends on its type,\nfor Android 4.1 */\n.ui-input-text input[type=number]::-webkit-outer-spin-button {\n\tmargin: 0;\n}\n/* Resolves issue #5756: Textinput in IE10 has a default clear button */\n.ui-input-text input::-ms-clear,\n.ui-input-search input::-ms-clear {\n\tdisplay: none;\n}\n.ui-input-text input:focus,\n.ui-input-search input:focus {\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n\tbox-shadow: none;\n}\ntextarea.ui-input-text.ui-textinput-autogrow {\n\toverflow: hidden;\n}\n.ui-textinput-autogrow-resize {\n\t-webkit-transition: height 0.25s;\n\t-o-transition: height 0.25s;\n\t-moz-transition: height 0.25s;\n\ttransition: height 0.25s;\n}\n.ui-flipswitch {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\twidth: 5.875em; /* Override this and padding-left in next rule if you use labels other than \"on/off\" and need more space */\n\theight: 1.875em;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tmargin: .5em 0;\n\toverflow: hidden;\n\t-webkit-transition-property: padding, width, background-color, color, border-color;\n\t-moz-transition-property: padding, width, background-color, color, border-color;\n\t-o-transition-property: padding, width, background-color, color, border-color;\n\ttransition-property: padding, width, background-color, color, border-color;\n\t-webkit-transition-duration: 100ms;\n\t-moz-transition-duration: 100ms;\n\t-o-transition-duration: 100ms;\n\ttransition-duration: 100ms;\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\tcursor: pointer;\n}\n.ui-flipswitch.ui-flipswitch-active {\n\tpadding-left: 4em;  /* Override this and width in previous rule if you use labels other than \"on/off\" and need more space */\n\twidth: 1.875em;\n}\n.ui-flipswitch-input {\n\tposition: absolute;\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n\tborder: 0;\n\toutline: 0;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on,\n.ui-flipswitch .ui-flipswitch-off {\n\tfloat: left;\n\theight: 1.75em;\n\tmargin: .0625em;\n\tline-height: 1.65em;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on {\n\twidth: 1.75em;\n\tpadding: 0;\n\ttext-indent: -2.6em; /* Override this to center text if you use a label other than \"on\" */\n\ttext-align: left;\n\tborder-width: 1px;\n\tborder-style: solid;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-radius: inherit;\n\toverflow: visible;\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n.ui-flipswitch .ui-flipswitch-off {\n\tpadding: 1px;\n\ttext-indent: 1em; /* Override this to center text if you use a label other than \"off\" */\n}\n/* Override field container CSS to prevent the flipswitch from becomming full width */\nhtml .ui-field-contain > label + .ui-flipswitch,\nhtml .ui-popup .ui-field-contain > label + .ui-flipswitch {\n\tdisplay: inline-block;\n\twidth: 5.875em; /* If you override the width for .ui-flipswitch you should repeat the same value here */\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-field-contain .ui-flipswitch.ui-flipswitch-active,\n.ui-popup .ui-field-contain .ui-flipswitch.ui-flipswitch-active {\n\twidth: 1.875em;\n}\n.ui-table {\n\tborder: 0;\n\tborder-collapse: collapse;\n\tpadding: 0;\n\twidth: 100%;\n}\n.ui-table th,\n.ui-table td {\n\tline-height: 1.5em;\n\ttext-align: left;\n\tpadding: .4em .5em;\n\tvertical-align:top;\n}\n.ui-table th .ui-btn,\n.ui-table td .ui-btn {\n\tline-height: normal;\n}\n.ui-table th {\n\tfont-weight: bold;\n}\n.ui-table caption {\n\ttext-align: left;\n\tmargin-bottom: 1.4em;\n\topacity: .5;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-columntoggle-btn {\n\tfloat: right;\n\tmargin-bottom: .8em;\n}\n/* Remove top/bottom margins around the fieldcontain on check list */\n.ui-table-columntoggle-popup fieldset {\n\tmargin:0;\n}\n.ui-table-columntoggle {\n\tclear: both;\n}\n/* Hide all prioritized columns by default */\n@media only all {\n\tth.ui-table-priority-6,\n\ttd.ui-table-priority-6,\n\tth.ui-table-priority-5,\n\ttd.ui-table-priority-5,\n\tth.ui-table-priority-4,\n\ttd.ui-table-priority-4,\n\tth.ui-table-priority-3,\n\ttd.ui-table-priority-3,\n\tth.ui-table-priority-2,\n\ttd.ui-table-priority-2,\n\tth.ui-table-priority-1,\n\ttd.ui-table-priority-1 {\n\t\tdisplay: none;\n\t}\n}\n/* Preset breakpoints if \".ui-responsive\" class added to table */\n/* Show priority 1 at 320px (20em x 16px) */\n@media screen and (min-width: 20em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-1 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 2 at 480px (30em x 16px) */\n@media screen and (min-width: 30em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-2 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 3 at 640px (40em x 16px) */\n@media screen and (min-width: 40em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-3 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 4 at 800px (50em x 16px) */\n@media screen and (min-width: 50em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-4 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 5 at 960px (60em x 16px) */\n@media screen and (min-width: 60em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-5 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 6 at 1,120px (70em x 16px) */\n@media screen and (min-width: 70em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-6 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Unchecked manually: Always hide */\n.ui-table-columntoggle th.ui-table-cell-hidden,\n.ui-table-columntoggle td.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden {\n\tdisplay: none;\n}\n/* Checked manually: Always show */\n.ui-table-columntoggle th.ui-table-cell-visible,\n.ui-table-columntoggle td.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible {\n\tdisplay: table-cell;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-reflow td .ui-table-cell-label,\n.ui-table-reflow th .ui-table-cell-label { \n\tdisplay: none;\n}\n/* Mobile first styles: Begin with the stacked presentation at narrow widths */ \n@media only all {\n\t/* Hide the table headers */ \n\t.ui-table-reflow thead td, \n\t.ui-table-reflow thead th {\n\t\tdisplay: none;\n\t}\n\t/* Show the table cells as a block level element */ \n\t.ui-table-reflow td,\n\t.ui-table-reflow th { \n\t\ttext-align: left;\n\t\tdisplay: block;\n\t}\n\t/* Add a fair amount of top margin to visually separate each row when stacked */  \n\t.ui-table-reflow tbody th {\n\t\tmargin-top: 3em;\n\t}\n\t/* Make the label elements a percentage width */ \n\t.ui-table-reflow td .ui-table-cell-label,\n\t.ui-table-reflow th .ui-table-cell-label { \n\t\tpadding: .4em; \n\t\tmin-width: 30%; \n\t\tdisplay: inline-block;\n\t\tmargin: -.4em 1em -.4em -.4em;\n\t}\n\t/* For grouped headers, have a different style to visually separate the levels by classing the first label in each col group */ \n\t.ui-table-reflow th .ui-table-cell-label-top,\n\t.ui-table-reflow td .ui-table-cell-label-top {\n\t\tdisplay: block;\n\t\tpadding: .4em 0;\n\t\tmargin: .4em 0;\n\t\ttext-transform: uppercase;\n\t\tfont-size: .9em;\n\t\tfont-weight: normal;\n\t}\n}\n/* Breakpoint to show as a standard table at 560px (35em x 16px) or wider */ \n@media ( min-width: 35em ) {\n\t/* Show the table header rows */ \n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th,\n\t.ui-table-reflow.ui-responsive tbody th,\n\t.ui-table-reflow.ui-responsive tbody td,\n\t.ui-table-reflow.ui-responsive thead td,\n\t.ui-table-reflow.ui-responsive thead th {\n\t\tdisplay: table-cell;\n\t\tmargin: 0;\n\t}\n\t/* Hide the labels in each cell */ \n\t.ui-table-reflow.ui-responsive td .ui-table-cell-label,\n\t.ui-table-reflow.ui-responsive th .ui-table-cell-label { \n\t\tdisplay: none;\n\t}\n}\n/* Hack to make IE9 and WP7.5 treat cells like block level elements, scoped to ui-responsive class */ \n/* Applied in a max-width media query up to the table layout breakpoint so we don't need to negate this*/ \n@media ( max-width: 35em ) {\n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th {\n\t\twidth: 100%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t\tfloat: left;\n\t\tclear: left;\n\t}\n}\n/* Panel */\n.ui-panel {\n\twidth: 17em;\n\tmin-height: 100%;\n\tmax-height: none;\n\tborder-width: 0;\n\tposition: absolute;\n\ttop: 0;\n\tdisplay: block;\n}\n.ui-panel-closed {\n\twidth: 0;\n\tmax-height: 100%;\n\toverflow: hidden;\n\tvisibility: hidden;\n\tleft: 0;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-panel-fixed {\n\tposition: fixed;\n\tbottom: -1px; /* Fixes gap on Chrome for Android */\n\tpadding-bottom: 1px;\n}\n.ui-panel-display-reveal {\n\tz-index: 1;\n}\n.ui-panel-display-push {\n\tz-index: 999;\n}\n.ui-panel-display-overlay {\n\tz-index: 1001; /* Fixed toolbars have z-index 1000 */\n}\n.ui-panel-inner {\n\tpadding: 1em;\n}\n/* Container, page and wrapper */\n.ui-panel-page-container {\n\toverflow-x: visible;\n}\n.ui-panel-page-container-themed .ui-page-active {\n\tbackground: none;\n}\n.ui-panel-wrapper {\n\tposition: relative;\n\tmin-height: inherit;\n\tborder: 0;\n\toverflow-x: hidden;\n\tz-index: 999;\n}\n/* Fixed toolbars */\n.ui-panel-fixed-toolbar {\n\toverflow-x: hidden;\n}\n/* Dismiss */\n.ui-panel-dismiss {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\theight: 100%;\n\tz-index: 1002;\n\tdisplay: none;\n}\n.ui-panel-dismiss-open {\n\tdisplay: block;\n}\n/* Animate class is added to panel, wrapper and fixed toolbars */\n.ui-panel-animate {\n\t-webkit-transition: -webkit-transform 300ms ease;\n\t-webkit-transition-duration: 300ms;\n\t-moz-transition: -moz-transform 300ms ease;\n\ttransition: transform 300ms ease;\n}\n/* Fix for Windows Phone issue #6349: unset the transition for transforms in case of fixed toolbars. */\n@media screen and ( max-device-width: 768px ) {\n\t.ui-page-header-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-page-footer-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: none;\n\t}\n\t/* We need a transitionend event ... */\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: -ms-transform 1ms;\n\t\t-ms-transform: rotate(0deg);\n\t}\n}\n/* Hardware acceleration for smoother transitions on WebKit browsers */\n.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal) {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translate3d(0,0,0);\n}\n/* Panel positioning (for overlay and push) */\n/* Panel left closed */\n.ui-panel-position-left {\n\tleft: -17em;\n}\n/* Panel left closed animated */\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-push {\n\tleft: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Panel left open */\n.ui-panel-position-left.ui-panel-display-reveal, /* Unset \"panel left closed\" for reveal */\n.ui-panel-open.ui-panel-position-left {\n\tleft: 0;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Panel right closed */\n.ui-panel-position-right {\n\tright: -17em;\n}\n/* Panel right closed animated */\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-push {\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-position-right.ui-panel-display-reveal, /* Unset \"panel right closed\" for reveal */\n.ui-panel-position-right.ui-panel-open {\n\tright: 0;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Wrapper and fixed toolbars positioning (for reveal and push) */\n/* Panel left open */\n.ui-panel-page-content-position-left {\n\tleft: 17em;\n\tright: -17em;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-page-content-position-left {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-page-content-position-right {\n\tleft: -17em;\n\tright: 17em;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-page-content-position-right {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Dismiss model open */\n.ui-panel-dismiss-open.ui-panel-dismiss-position-left {\n\tleft: 17em;\n}\n.ui-panel-dismiss-open.ui-panel-dismiss-position-right {\n\tright: 17em;\n}\n/* Shadows and borders */\n.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-display-overlay {\n\t-webkit-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-overlay {\n\t-webkit-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-panel-page-content-position-left.ui-panel-page-content-display-push {\n\tmargin-left: 1px;\n\twidth: auto;\n}\n.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\tborder-left-width: 1px;\n\tmargin-left: -1px;\n}\n.ui-panel-page-content-position-right.ui-panel-page-content-display-push {\n\tmargin-right: 1px;\n\twidth: auto;\n}\n/* Responsive: wrap on wide viewports once open */\n@media (min-width:55em) {\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left {\n\t\tmargin-right: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right {\n\t\tmargin-left: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open {\n\t\twidth: auto;\t\n\t}\n\t.ui-responsive-panel .ui-panel-dismiss-display-push,\n\t.ui-responsive-panel.ui-page-active ~ .ui-panel-dismiss-display-push {\n\t\tdisplay: none;\n\t}\n}\n.ui-tabs {\n\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n\tpadding: .2em;\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile.icons-1.4.5.css",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n/* SVG icons */\n.ui-icon-action:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-alert:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8%20C6.447%2C8%2C6%2C7.553%2C6%2C7V5c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-audio:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-back:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-bars:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5%20C4.447%2C6%2C4%2C6.447%2C4%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1%20S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-camera:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2%20v6c0%2C1.104%2C0.896%2C2%2C2%2C2h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2%20C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-check:after,\n/* Used ui-checkbox-on twice to increase specificity. If active state has background-image for gradient this rule overrides. */\nhtml .ui-btn.ui-checkbox-on.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-clock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2%20c-0.158%2C0-0.311%2C0.023-0.457%2C0.058C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9%20c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-comment:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-delete:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-edit:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-eye:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-forward:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-gear:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-grid:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-heart:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C1.872c-2-3-7-2-7%2C2c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.479%2C3%2C3c0.583-0.521%2C3-3%2C3-3s4-4%2C4-7%20C14-0.128%2C9-1.128%2C7%2C1.872z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-home:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-info:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-location:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4%20s0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-lock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848%20C6.207%2C9.673%2C6%2C9.366%2C6%2C9c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-mail:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-minus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20style%3D%22fill%3A%23FFFFFF%3B%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-phone:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%22-0.01%200.008%2014%2014%22%20style%3D%22enable-background%3Anew%20-0.01%200.008%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M6.939%2C9.189C6.165%2C8.557%2C5.271%2C7.705%2C4.497%2C6.744C3.953%2C6.071%2C3.473%2C5.363%2C3.969%2C4.866l-3.482-3.48%20C-0.021%2C2.02-1.146%2C5.04%2C3.675%2C9.984c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.4C8.725%2C10.568%2C8.113%2C10.146%2C6.939%2C9.189z%20%20M13.82%2C11.519v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.211-0.546-0.205-0.754%2C0.002L9.455%2C9.831l3.403%2C3.407%20c0%2C0%2C0.962-0.96%2C0.961-0.961l0.002-0.001C14.043%2C12.056%2C14.021%2C11.721%2C13.82%2C11.519z%20M5.192%2C3.644V3.642%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.881c0%2C0-2.726-2.725-2.727-2.726C2.255-0.055%2C1.92-0.05%2C1.712%2C0.156L0.751%2C1.121l3.479%2C3.482%20C4.231%2C4.604%2C5.192%2C3.645%2C5.192%2C3.644z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-plus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-power:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455%20C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773%20C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773%20c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811%20C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1%20c-0.553%2C0-1%2C0.447-1%2C1v6C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11%20C4.791%2C11%2C3%2C9.209%2C3%2C7z%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4%20h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-search:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5%20s2.463%2C5.5%2C5.5%2C5.5c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-shop:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5%20S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5%20S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-star:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-tag:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-user:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-video:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n/* Alt icons */\n.ui-alt-icon.ui-icon-action:after,\n.ui-alt-icon .ui-icon-action:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-alert:after,\n.ui-alt-icon .ui-icon-alert:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8C6.447%2C8%2C6%2C7.553%2C6%2C7V5%20c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d:after,\n.ui-alt-icon .ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d-l:after,\n.ui-alt-icon .ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d-r:after,\n.ui-alt-icon .ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-l:after,\n.ui-alt-icon .ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-r:after,\n.ui-alt-icon .ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u:after,\n.ui-alt-icon .ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u-l:after,\n.ui-alt-icon .ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u-r:after,\n.ui-alt-icon .ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-audio:after,\n.ui-alt-icon .ui-icon-audio:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-back:after,\n.ui-alt-icon .ui-icon-back:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-bars:after,\n.ui-alt-icon .ui-icon-bars:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h12%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-bullets:after,\n.ui-alt-icon .ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5C4.447%2C6%2C4%2C6.447%2C4%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h8%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-calendar:after,\n.ui-alt-icon .ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-camera:after,\n.ui-alt-icon .ui-icon-camera:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2%20h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-d:after,\n.ui-alt-icon .ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-l:after,\n.ui-alt-icon .ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-r:after,\n.ui-alt-icon .ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-u:after,\n.ui-alt-icon .ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-check:after,\n.ui-alt-icon .ui-icon-check:after,\nhtml .ui-alt-icon.ui-btn.ui-checkbox-on:after,\nhtml .ui-alt-icon .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-clock:after,\n.ui-alt-icon .ui-icon-clock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-cloud:after,\n.ui-alt-icon .ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2c-0.158%2C0-0.311%2C0.023-0.457%2C0.058%20C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07%20C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-comment:after,\n.ui-alt-icon .ui-icon-comment:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-delete:after,\n.ui-alt-icon .ui-icon-delete:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-edit:after,\n.ui-alt-icon .ui-icon-edit:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-eye:after,\n.ui-alt-icon .ui-icon-eye:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-forbidden:after,\n.ui-alt-icon .ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-forward:after,\n.ui-alt-icon .ui-icon-forward:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-gear:after,\n.ui-alt-icon .ui-icon-gear:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-grid:after,\n.ui-alt-icon .ui-icon-grid:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-heart:after,\n.ui-alt-icon .ui-icon-heart:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C1.958c-2-3-7-2.128-7%2C1.872c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.48%2C3%2C3c0.583-0.52%2C3-3%2C3-3s4-4%2C4-7C14-0.169%2C9-1.042%2C7%2C1.958z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-home:after,\n.ui-alt-icon .ui-icon-home:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-info:after,\n.ui-alt-icon .ui-icon-info:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-location:after,\n.ui-alt-icon .ui-icon-location:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4s0.896-2%2C2-2%20c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-lock:after,\n.ui-alt-icon .ui-icon-lock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848C6.207%2C9.673%2C6%2C9.366%2C6%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-mail:after,\n.ui-alt-icon .ui-icon-mail:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-minus:after,\n.ui-alt-icon .ui-icon-minus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-navigation:after,\n.ui-alt-icon .ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-phone:after,\n.ui-alt-icon .ui-icon-phone:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M6.949%2C9.182C6.175%2C8.549%2C5.281%2C7.697%2C4.507%2C6.736C3.963%2C6.063%2C3.483%2C5.355%2C3.979%2C4.858l-3.482-3.48%20c-0.508%2C0.634-1.633%2C3.654%2C3.188%2C8.598c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.399C8.734%2C10.561%2C8.123%2C10.139%2C6.949%2C9.182z%20%20M13.83%2C11.512v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.212-0.546-0.205-0.754%2C0.002L9.465%2C9.823l3.402%2C3.407%20c0%2C0%2C0.963-0.961%2C0.961-0.961l0.002-0.002C14.053%2C12.049%2C14.031%2C11.713%2C13.83%2C11.512z%20M5.202%2C3.636V3.634%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.873c0%2C0-2.726-2.725-2.727-2.726c-0.21-0.21-0.545-0.205-0.753%2C0.001L0.761%2C1.113L4.24%2C4.595%20C4.241%2C4.596%2C5.202%2C3.637%2C5.202%2C3.636z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-plus:after,\n.ui-alt-icon .ui-icon-plus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-power:after,\n.ui-alt-icon .ui-icon-power:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773%20s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863%20c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365%20c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773%20C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1c-0.553%2C0-1%2C0.447-1%2C1v6%20C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-recycle:after,\n.ui-alt-icon .ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11C4.791%2C11%2C3%2C9.209%2C3%2C7z%20%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-refresh:after,\n.ui-alt-icon .ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-search:after,\n.ui-alt-icon .ui-icon-search:after,\n.ui-input-search:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5s2.463%2C5.5%2C5.5%2C5.5%20c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-shop:after,\n.ui-alt-icon .ui-icon-shop:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5%20S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5%20S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-star:after,\n.ui-alt-icon .ui-icon-star:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-tag:after,\n.ui-alt-icon .ui-icon-tag:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-user:after,\n.ui-alt-icon .ui-icon-user:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-video:after,\n.ui-alt-icon .ui-icon-video:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n/* PNG icons */\n.ui-nosvg .ui-icon-action:after {\n\tbackground-image: url(\"images/icons-png/action-white.png\");\n}\n.ui-nosvg .ui-icon-alert:after {\n\tbackground-image: url(\"images/icons-png/alert-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"images/icons-png/arrow-d-l-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"images/icons-png/arrow-d-r-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-d:after {\n\tbackground-image: url(\"images/icons-png/arrow-d-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-l:after {\n\tbackground-image: url(\"images/icons-png/arrow-l-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-r:after {\n\tbackground-image: url(\"images/icons-png/arrow-r-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"images/icons-png/arrow-u-l-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"images/icons-png/arrow-u-r-white.png\");\n}\n.ui-nosvg .ui-icon-arrow-u:after {\n\tbackground-image: url(\"images/icons-png/arrow-u-white.png\");\n}\n.ui-nosvg .ui-icon-audio:after {\n\tbackground-image: url(\"images/icons-png/audio-white.png\");\n}\n.ui-nosvg .ui-icon-back:after {\n\tbackground-image: url(\"images/icons-png/back-white.png\");\n}\n.ui-nosvg .ui-icon-bars:after {\n\tbackground-image: url(\"images/icons-png/bars-white.png\");\n}\n.ui-nosvg .ui-icon-bullets:after {\n\tbackground-image: url(\"images/icons-png/bullets-white.png\");\n}\n.ui-nosvg .ui-icon-calendar:after {\n\tbackground-image: url(\"images/icons-png/calendar-white.png\");\n}\n.ui-nosvg .ui-icon-camera:after {\n\tbackground-image: url(\"images/icons-png/camera-white.png\");\n}\n.ui-nosvg .ui-icon-carat-d:after {\n\tbackground-image: url(\"images/icons-png/carat-d-white.png\");\n}\n.ui-nosvg .ui-icon-carat-l:after {\n\tbackground-image: url(\"images/icons-png/carat-l-white.png\");\n}\n.ui-nosvg .ui-icon-carat-r:after {\n\tbackground-image: url(\"images/icons-png/carat-r-white.png\");\n}\n.ui-nosvg .ui-icon-carat-u:after {\n\tbackground-image: url(\"images/icons-png/carat-u-white.png\");\n}\n.ui-nosvg .ui-icon-check:after,\nhtml.ui-nosvg .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(\"images/icons-png/check-white.png\");\n}\n.ui-nosvg .ui-icon-clock:after {\n\tbackground-image: url(\"images/icons-png/clock-white.png\");\n}\n.ui-nosvg .ui-icon-cloud:after {\n\tbackground-image: url(\"images/icons-png/cloud-white.png\");\n}\n.ui-nosvg .ui-icon-comment:after {\n\tbackground-image: url(\"images/icons-png/comment-white.png\");\n}\n.ui-nosvg .ui-icon-delete:after {\n\tbackground-image: url(\"images/icons-png/delete-white.png\");\n}\n.ui-nosvg .ui-icon-edit:after {\n\tbackground-image: url(\"images/icons-png/edit-white.png\");\n}\n.ui-nosvg .ui-icon-eye:after {\n\tbackground-image: url(\"images/icons-png/eye-white.png\");\n}\n.ui-nosvg .ui-icon-forbidden:after {\n\tbackground-image: url(\"images/icons-png/forbidden-white.png\");\n}\n.ui-nosvg .ui-icon-forward:after {\n\tbackground-image: url(\"images/icons-png/forward-white.png\");\n}\n.ui-nosvg .ui-icon-gear:after {\n\tbackground-image: url(\"images/icons-png/gear-white.png\");\n}\n.ui-nosvg .ui-icon-grid:after {\n\tbackground-image: url(\"images/icons-png/grid-white.png\");\n}\n.ui-nosvg .ui-icon-heart:after {\n\tbackground-image: url(\"images/icons-png/heart-white.png\");\n}\n.ui-nosvg .ui-icon-home:after {\n\tbackground-image: url(\"images/icons-png/home-white.png\");\n}\n.ui-nosvg .ui-icon-info:after {\n\tbackground-image: url(\"images/icons-png/info-white.png\");\n}\n.ui-nosvg .ui-icon-location:after {\n\tbackground-image: url(\"images/icons-png/location-white.png\");\n}\n.ui-nosvg .ui-icon-lock:after {\n\tbackground-image: url(\"images/icons-png/lock-white.png\");\n}\n.ui-nosvg .ui-icon-mail:after {\n\tbackground-image: url(\"images/icons-png/mail-white.png\");\n}\n.ui-nosvg .ui-icon-minus:after {\n\tbackground-image: url(\"images/icons-png/minus-white.png\");\n}\n.ui-nosvg .ui-icon-navigation:after {\n\tbackground-image: url(\"images/icons-png/navigation-white.png\");\n}\n.ui-nosvg .ui-icon-phone:after {\n\tbackground-image: url(\"images/icons-png/phone-white.png\");\n}\n.ui-nosvg .ui-icon-plus:after {\n\tbackground-image: url(\"images/icons-png/plus-white.png\");\n}\n.ui-nosvg .ui-icon-power:after {\n\tbackground-image: url(\"images/icons-png/power-white.png\");\n}\n.ui-nosvg .ui-icon-recycle:after {\n\tbackground-image: url(\"images/icons-png/recycle-white.png\");\n}\n.ui-nosvg .ui-icon-refresh:after {\n\tbackground-image: url(\"images/icons-png/refresh-white.png\");\n}\n.ui-nosvg .ui-icon-search:after {\n\tbackground-image: url(\"images/icons-png/search-white.png\");\n}\n.ui-nosvg .ui-icon-shop:after {\n\tbackground-image: url(\"images/icons-png/shop-white.png\");\n}\n.ui-nosvg .ui-icon-star:after {\n\tbackground-image: url(\"images/icons-png/star-white.png\");\n}\n.ui-nosvg .ui-icon-tag:after {\n\tbackground-image: url(\"images/icons-png/tag-white.png\");\n}\n.ui-nosvg .ui-icon-user:after {\n\tbackground-image: url(\"images/icons-png/user-white.png\");\n}\n.ui-nosvg .ui-icon-video:after {\n\tbackground-image: url(\"images/icons-png/video-white.png\");\n}\n/* Alt icons */\n.ui-nosvg .ui-alt-icon.ui-icon-action:after,\n.ui-nosvg .ui-alt-icon .ui-icon-action:after {\n\tbackground-image: url(\"images/icons-png/action-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-alert:after,\n.ui-nosvg .ui-alt-icon .ui-icon-alert:after {\n\tbackground-image: url(\"images/icons-png/alert-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-d:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-d:after {\n\tbackground-image: url(\"images/icons-png/arrow-d-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"images/icons-png/arrow-d-l-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-d-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"images/icons-png/arrow-d-r-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-l:after {\n\tbackground-image: url(\"images/icons-png/arrow-l-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-r:after {\n\tbackground-image: url(\"images/icons-png/arrow-r-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-u:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-u:after {\n\tbackground-image: url(\"images/icons-png/arrow-u-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"images/icons-png/arrow-u-l-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-arrow-u-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"images/icons-png/arrow-u-r-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-audio:after,\n.ui-nosvg .ui-alt-icon .ui-icon-audio:after {\n\tbackground-image: url(\"images/icons-png/audio-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-back:after,\n.ui-nosvg .ui-alt-icon .ui-icon-back:after {\n\tbackground-image: url(\"images/icons-png/back-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-bars:after,\n.ui-nosvg .ui-alt-icon .ui-icon-bars:after {\n\tbackground-image: url(\"images/icons-png/bars-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-bullets:after,\n.ui-nosvg .ui-alt-icon .ui-icon-bullets:after {\n\tbackground-image: url(\"images/icons-png/bullets-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-calendar:after,\n.ui-nosvg .ui-alt-icon .ui-icon-calendar:after {\n\tbackground-image: url(\"images/icons-png/calendar-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-camera:after,\n.ui-nosvg .ui-alt-icon .ui-icon-camera:after {\n\tbackground-image: url(\"images/icons-png/camera-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-d:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-d:after {\n\tbackground-image: url(\"images/icons-png/carat-d-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-l:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-l:after {\n\tbackground-image: url(\"images/icons-png/carat-l-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-r:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-r:after {\n\tbackground-image: url(\"images/icons-png/carat-r-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-carat-u:after,\n.ui-nosvg .ui-alt-icon .ui-icon-carat-u:after {\n\tbackground-image: url(\"images/icons-png/carat-u-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-check:after,\n.ui-nosvg .ui-alt-icon .ui-icon-check:after,\n.ui-nosvg .ui-alt-icon.ui-btn.ui-checkbox-on:after,\n.ui-nosvg .ui-alt-icon .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(\"images/icons-png/check-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-clock:after,\n.ui-nosvg .ui-alt-icon .ui-icon-clock:after {\n\tbackground-image: url(\"images/icons-png/clock-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-cloud:after,\n.ui-nosvg .ui-alt-icon .ui-icon-cloud:after {\n\tbackground-image: url(\"images/icons-png/cloud-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-comment:after,\n.ui-nosvg .ui-alt-icon .ui-icon-comment:after {\n\tbackground-image: url(\"images/icons-png/comment-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-delete:after,\n.ui-nosvg .ui-alt-icon .ui-icon-delete:after {\n\tbackground-image: url(\"images/icons-png/delete-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-edit:after,\n.ui-nosvg .ui-alt-icon .ui-icon-edit:after {\n\tbackground-image: url(\"images/icons-png/edit-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-eye:after,\n.ui-nosvg .ui-alt-icon .ui-icon-eye:after {\n\tbackground-image: url(\"images/icons-png/eye-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-forbidden:after,\n.ui-nosvg .ui-alt-icon .ui-icon-forbidden:after {\n\tbackground-image: url(\"images/icons-png/forbidden-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-forward:after,\n.ui-nosvg .ui-alt-icon .ui-icon-forward:after {\n\tbackground-image: url(\"images/icons-png/forward-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-gear:after,\n.ui-nosvg .ui-alt-icon .ui-icon-gear:after {\n\tbackground-image: url(\"images/icons-png/gear-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-grid:after,\n.ui-nosvg .ui-alt-icon .ui-icon-grid:after {\n\tbackground-image: url(\"images/icons-png/grid-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-heart:after,\n.ui-nosvg .ui-alt-icon .ui-icon-heart:after {\n\tbackground-image: url(\"images/icons-png/heart-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-home:after,\n.ui-nosvg .ui-alt-icon .ui-icon-home:after {\n\tbackground-image: url(\"images/icons-png/home-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-info:after,\n.ui-nosvg .ui-alt-icon .ui-icon-info:after {\n\tbackground-image: url(\"images/icons-png/info-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-location:after,\n.ui-nosvg .ui-alt-icon .ui-icon-location:after {\n\tbackground-image: url(\"images/icons-png/location-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-lock:after,\n.ui-nosvg .ui-alt-icon .ui-icon-lock:after {\n\tbackground-image: url(\"images/icons-png/lock-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-mail:after,\n.ui-nosvg .ui-alt-icon .ui-icon-mail:after {\n\tbackground-image: url(\"images/icons-png/mail-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-minus:after,\n.ui-nosvg .ui-alt-icon .ui-icon-minus:after {\n\tbackground-image: url(\"images/icons-png/minus-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-navigation:after,\n.ui-nosvg .ui-alt-icon .ui-icon-navigation:after {\n\tbackground-image: url(\"images/icons-png/navigation-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-phone:after,\n.ui-nosvg .ui-alt-icon .ui-icon-phone:after {\n\tbackground-image: url(\"images/icons-png/phone-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-plus:after,\n.ui-nosvg .ui-alt-icon .ui-icon-plus:after {\n\tbackground-image: url(\"images/icons-png/plus-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-power:after,\n.ui-nosvg .ui-alt-icon .ui-icon-power:after {\n\tbackground-image: url(\"images/icons-png/power-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-recycle:after,\n.ui-nosvg .ui-alt-icon .ui-icon-recycle:after {\n\tbackground-image: url(\"images/icons-png/recycle-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-refresh:after,\n.ui-nosvg .ui-alt-icon .ui-icon-refresh:after {\n\tbackground-image: url(\"images/icons-png/refresh-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-search:after,\n.ui-nosvg .ui-alt-icon .ui-icon-search:after,\n.ui-nosvg .ui-input-search:after {\n\tbackground-image: url(\"images/icons-png/search-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-shop:after,\n.ui-nosvg .ui-alt-icon .ui-icon-shop:after {\n\tbackground-image: url(\"images/icons-png/shop-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-star:after,\n.ui-nosvg .ui-alt-icon .ui-icon-star:after {\n\tbackground-image: url(\"images/icons-png/star-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-tag:after,\n.ui-nosvg .ui-alt-icon .ui-icon-tag:after {\n\tbackground-image: url(\"images/icons-png/tag-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-user:after,\n.ui-nosvg .ui-alt-icon .ui-icon-user:after {\n\tbackground-image: url(\"images/icons-png/user-black.png\");\n}\n.ui-nosvg .ui-alt-icon.ui-icon-video:after,\n.ui-nosvg .ui-alt-icon .ui-icon-video:after {\n\tbackground-image: url(\"images/icons-png/video-black.png\");\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile.inline-png-1.4.5.css",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n.ui-icon-action:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAIVJREFUOMtjYCAC/P//fxYQszGQCv5DwDEgliRHIwg8A2JLdEEYaICKqwHxciD+gCb/E4jTGHBosgPiL/+xA1SNSM7iBeIXQPwDiOuAWByvU5E05gPxZyC2xhs4WDTuBuJwtMCZCYsOmHewaZyLJ3Qb4GqxaDQiFC1YNRITn9TRSAqgSCMAGL+QeSGFbu0AAAAASUVORK5CYII=\");\n}\n.ui-icon-alert:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJVJREFUOMu9z7ENgkAUgOGj0I6eBXQCg8QRdAhdwiV0CF2CIRxBF6Cn08LP5oxIIEjjX13evS+5C6EnbLAOY8IUN1wxGQP3Pu1/RRnqBqyR/QLPEeQo4vk0hJZ4QmMmzvI+lODyfl8LindJF9z5rsCqNdu2UYrKcBXSJjx2LC3in9sd3miOR8fCsuOpcMcsoDS+Mvy9F2w1bmFOO7YjAAAAAElFTkSuQmCC\");\n}\n.ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE9JREFUOMut0VsKACAIBECP3tG8mSFZRGVujwV/wkE0IjAikrToJIZq0g3CsIMK9PQWWcM0OkQdbI8QGqCGIbSAAl/wCgWQo7/6PvFpRxdn/yOefcvwdI0AAAAASUVORK5CYII=\");\n}\n.ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE1JREFUOMtjYICC////N4AwAykAqgkGGsjRRLRmJhzi9UTZjMNWnDajiBOrGaaOJJuR5Ulx9gFkDql+xq+RGM2EQvsAfWwky4/EaAIBAH/xh5XOyrKIAAAAAElFTkSuQmCC\");\n}\n.ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADdJREFUOMtjYMAC/qMBBmLBqEZKNQLFG/6TDhrI0dxAjs0N5Di7gVDANJCsCYfmBgZSAFQzTk0AIbtHzgIaJM8AAAAASUVORK5CYII=\");\n}\n.ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAD5JREFUOMul0kEKADAMAsE8PT/fXktpqVHvA8FY9QjQNQ3QABYawR3J8EQSvKFfLJRB+9SonOgd0QCiyakjXzjeR87keFK/AAAAAElFTkSuQmCC\");\n}\n.ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADpJREFUOMu90rENADAIA0FG/82dgooiSDgK31+DiWiSRDgpw4VzrBourFjzcGHiTcjbcX7PwdrLXdEBwEtHzn8VrGMAAAAASUVORK5CYII=\");\n}\n.ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEtJREFUOMtj+E8caGBAB2RpIkIjdk0ENB5gwAdoYSNJfjxATqg2QPkNRGnGJkiUZlx+INpmUjUz4dPIyMgIMr2RgVyAZnMDOZrhmgAEuoiZ+HH38AAAAABJRU5ErkJggg==\");\n}\n.ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEdJREFUOMu9z8ENACAIQ9GOzmhuVq+GSCke/Fd8AYEUyaARbjkYVR2GiuT6s/HpjwKtEgoUeW6j/G6ETjxG3YkaFdhDCdtoA045nn2X6PolAAAAAElFTkSuQmCC\");\n}\n.ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADlJREFUOMtjYMAB/v//3wDCDKQAqCYYaCBHE3GacWjCr5mAJuyaidSEqplETQSdjQJIiY5RjZRoBADXbkfOGh7ilQAAAABJRU5ErkJggg==\");\n}\n.ui-icon-audio:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAANxJREFUOMuV0rEuRFEQxvETL2DpZVEoVLyFJ1CJRKfabCKikbiJUhQa3kSj32K7DQqJwgugQVay8lOYleO654avmm/m/HMmM5NSg3CUxTO4wlZqE44xyfwa3nzprA2Sg5FfwV3UDkrQN4gd9CJewCPesZQw9FtTcBR+P3wv/GnSrCnYxRNe0cEcPnDbCgZ8HrmN8A8Y/wW8+DeIZTzjBbOYj1ZvEgaYFMDr8P3w/fAn+TqqBnAbuxEvxqDG6NZ3WRUOYBX3UdsrXU9VG856/PKzxQJ8WDvyS2zmbz4B8IPWAlHG2vgAAAAASUVORK5CYII=\");\n}\n.ui-icon-back:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJJJREFUOMtjYEAD////b2AgFYA0AfF/sjSRpBFZExT8AeLXQHwciCcAsQOxGrGBM0CsS0gzKxBLA7ELELcC8VOo+Ccg1iY6cIBCXEC8Fqp5M05n4xCXgGr8TGqoC5OrsRGqcS+xGkABVQ/E/6AaXQlpUATiYiC+C9UA0lhKjE3I4CYQexDrxGdAvBSIfYGYCV0eAL8TDNuB31nNAAAAAElFTkSuQmCC\");\n}\n.ui-icon-bars:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAClJREFUOMtjYKA7+P///8n/pIMTII3HydB4lGHUjzTy4xly/XhiaPgRALzOTCcBlK2mAAAAAElFTkSuQmCC\");\n}\n.ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADpJREFUOMtjYKA7+P///0kgPo7GJwROgBQeB+KjSBqPE6HxKMOoH2nkxzNgN6PyifLjCTQ/nhicfgQA/VEZvCqEuYoAAAAASUVORK5CYII=\");\n}\n.ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADFJREFUOMtjYICC////nwTi4ww4AFDuDBCfQBYgCwwljWQDZBNIYpOtcdSpeGwhVyMA6YDNaA+GXWMAAAAASUVORK5CYII=\");\n}\n.ui-icon-camera:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJ1JREFUOMtjYKAW+P//vzoQ1wBxAxSD2KrYFHIBcSaSwqf/McFjJPksIOYEadz8n3SwCaTxDxaJh0A8AYj7oGx08IcBi+ABIBaFOh/kLBEgPoiuCJtGAzTnbwJiQ2I0sgDxLyT+TyBmJdbGTUj89UBsTIzGQ0h+zICyj2DT+BeL5kdA3A8N2ce4QnUTGfG4HqSREy3lEMIZ4JRDLgAADx5bua1tC5oAAAAASUVORK5CYII=\");\n}\n.ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHdJREFUKJHV0D0OwjAMBtCcpiBSVn7uv8MpUNVMwAUeSyuiKG3DyLdZ9rMlh/BfwR6nhrkLurnYYcAT5xV0xRsPdAF331TxdOmVzd0CIsYlXEEjDnOzildRtjkiFbhEcekBJd5GGe4LnDZRho8TSOibUIF/Qy35ADEDFfz8Tu1HAAAAAElFTkSuQmCC\");\n}\n.ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFNJREFUOMtjYMAD/v//rwvE54FYhYFYAFSsB8Sv/0PAUyBWJVUTCLwHYmNyNJkQo+kNqZr06aOJIo14NJuSEnfImj+Qqvk1mmYzumt+TGp6xZnIAZYXFgOYoY9iAAAAAElFTkSuQmCC\");\n}\n.ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAGRJREFUOMtjYEAD////Vwfi80CsxUAsACrWAOLn/yHgJRBrE6vRDIg//EcAkjSbU1PzK0o161CiWZdYjR9JshWowIIcTZZYNGkTo+kTSdEBdd4nkuMQqEgNiJ+SHPFIms8RSuQASm4V+ztdam4AAAAASUVORK5CYII=\");\n}\n.ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAG5JREFUOMtjYKA2+P//vz4Ik6PpDRTrkaoJBghrBilA0wQDr3Fqhmp6jaT4PRQja9YlRpMJEJsC8QesmkEMbJqQDEXX/AqsGUicx6UJj+ZzIEEVIH6KSxOSZjOo5scgPTBBVSA2JiKqzOCahg4AAODRFgCi4LIMAAAAAElFTkSuQmCC\");\n}\n.ui-icon-check:after,\n/* Used ui-checkbox-on twice to increase specificity. If active state has background-image for gradient this rule overrides. */\nhtml .ui-btn.ui-checkbox-on.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE5JREFUOMu10DEKACEQQ1GPHl2QxUvHZsURQRJhfzfFKzIp/R1JkISLMmdQUeEebtAKvw053I+KRuUGncLpYxoS9kgfrDYK+LVRwM1GTh2KeDEWoG7NGwAAAABJRU5ErkJggg==\");\n}\n.ui-icon-clock:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAN5JREFUOMuNkl0KglAQhYeexA0kthWtVQRCq6gQWkBRi4mIaA/Zm2EbsYJ6STsjx7jYtTrwoXecP2euiKGyLHtgBc7gQTKwBL7YhA8jcCvbdQWRLaigwxoEwCEh2PBb8Q5me3WliZHsCA7GOabPBXjCf6oqNbqo1LBtaV4IB6EK/gjs03wSTk7l2AKphDaX53tH2pUY70/bGjJmCeWH4DOgb6oV97SP5bemfO41i8/lquIv1Wb0yUG3NkbGBdhyei7R9nbGBRg2M0ZcbpvyjyAj2NPl6p505CQF83d71As1WJi0XvrCDgAAAABJRU5ErkJggg==\");\n}\n.ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHRJREFUOMtjYBhw8P//f2EgTgTiWigtRIymSCD+/B8VfATiEHyabIH473/s4DcQm+PSuOs/fvAPiF8BsT+yJncg/vafOPASpqniP2ngCxBzgjS+/U862AjS+I4MjT9BGsvJ0LgO5k8XaIQ3EIEzgZiD/kkTAK0pr7/Ot6yrAAAAAElFTkSuQmCC\");\n}\n.ui-icon-comment:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEJJREFUOMtj+P//fyAQv/xPPHgFxP4MJGqCgZcM/8kEoxpppfEVGfpegDT6k5gIXgCxLwMyQJJsYCAFkKUJqpFoTQBdxXiyPJoNzQAAAABJRU5ErkJggg==\");\n}\n.ui-icon-delete:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFtJREFUOMulklEKwDAIQ83J153c0U1GK0ZG5o/ga4pNA4ty9zE7gGFFZY5leMSZM4srjjS0LKacgBtGLxmaW1k9q5J3tKLXnI/izbT/QmlVyRz5O+QAyJFTQ34BOkVgA0nxhd0AAAAASUVORK5CYII=\");\n}\n.ui-icon-edit:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAExJREFUOMtjYCAS/P//vwGEGUgBUE0w0ECuRsKakZ1HtK3YFBL0JxanEe28/yRpHPyaFEjWBNWYQLImqMYFJGuCajwA1QyyWYHYZAgAGGspdigXzkIAAAAASUVORK5CYII=\");\n}\n.ui-icon-eye:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJ9JREFUOMtjYBhQ8P//f0YgjgLig0D8FYoPQMUYcWmSgCrCBUBy4uia5ID4HlTBDyDOBmIBIOaDsn9A5UBq5GCa+IH4OpLJ2Vhck4MkD1LLDxJcheYkAajik0B8HMlwZLCSCYt3/yHRMDYjtkBBd2ouFjUFSPLXQH7HFTi5UAMFoJp+YgQOkqniBKJjP0Z0oCWASKgBX6D4AFSMcWCTJwDwblGBQMiLsgAAAABJRU5ErkJggg==\");\n}\n.ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAANZJREFUOMuF0jFuwkAUhOEtCT0R4iwh4hgu0uUM3AAU5TKIKk1OgSPlHCgUQMOXZrAsY8NIK9k7/v3ezttSWsIMn/jFGSf84AOz0ie842BYB1R90CUffOEFo6w5NvEuDZz22pVqTHo6Wsb/w7TkTNdK9QN4G39dEoS0N7kH4zXeriQ9GMUchDHO/rEk8ga8B+Mpe6eSOcG809YNjMX1vWS4sOkJowt/53nVHcfyAQx7PF/NqnUBtklvnDMtWpUueOv+ucpwh7S/gVrwFGvscEziNVZNe9E/AYkNLyf6mZAAAAAASUVORK5CYII=\");\n}\n.ui-icon-forward:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJVJREFUOMud0SEPQWEUBuA7I6iSTdFtfoNgJvkzNtE+QfcnRFFVFX9AECmaieYRfOGyue533/qeZ2c7J8tKBCGrEu+EqrAYY4AV9rji4TPhG/Rx8D8hj3q4xeKMJYbooFG0bRuLDZqlj4N7LNtJ78jBVuq5dxEuUuEowifmqKfgWYRwwhTdsniMY/5pKZtrmGCNy6+5F/zkDN/sPUM/AAAAAElFTkSuQmCC\");\n}\n.ui-icon-gear:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAANBJREFUOMuN0k1OAkEUReGKDVPsBUiCe/An6CZMCHERkLgABzpwr0rCAhoM/Tl56ktTQc+o07dud71TVUoFXOITe0zLKfCIOcZ488sLRrjDslaCHlvHbCPrscjFebz8ix7XuThOf+qwQotJPHeRbdBkEXmmVWX+dcpfMSthL9NWiueDNfsSyjOTSrEdrOkKpqH81FafUv6Mi+9gNJCzju21UdpF9o6z/MV7/+OAm1xcxhkd8FEpbNIFeBjOscAVmlCeZ2pwe1SqyJiF7d2PiAFfUWcCdKtjEnkAAAAASUVORK5CYII=\");\n}\n.ui-icon-grid:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAElJREFUOMtj+P///8n/CHCcAQjQxE5Axc4gizGCSAYkwAgExIgxMZAJQBpPIPGPQWlsYiexiJEBhlbgnCQyIKgXOGcIBcQQDxwAcK29sfGNuOEAAAAASUVORK5CYII=\");\n}\n.ui-icon-heart:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJhJREFUOMud0L0NwjAQgNErGAEGoU0WSYUEggGyVULFCFCyAgPQQQsU5NE4EuLfPOka258sXUREYIwldtiixiBNnc526c04UlTg7NkqzaMzisBGvnW8+e2bU+D4R3gItH+Ebb+cXEW/2SYjaqKHEfY/RHsM4x5KXD5EF5TxCipcX0RXVPEJpugeokn8AosUd5hFDswxfXd/AyJMQU8RkPn/AAAAAElFTkSuQmCC\");\n}\n.ui-icon-home:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADxJREFUOMtjYMAB/v//3wDCDKQAqCYYaCBHE3GacWjCr5mAJuyaidSEqplETZg2E6sDmx8p10iK3HDWCADqFJ92uuEinAAAAABJRU5ErkJggg==\");\n}\n.ui-icon-info:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJ1JREFUOMul0k0KwjAQQOHcQtF7SPEeQsHrKHo8S71IVdBVPzejaJ0u1AezSfKS+UkpL2COPY64RbTYYVYysMbFOGfUmdQPDi5QDdb6pxzpZS9VWCbrJ0xL1PQt2xKNeGNQRkZTonPG5BHx+pfY/iAeSgz3W3FTMIvhps1J5A6Tx0adfICMHqvhrXUMd4zuQ3qRp9iiwTXigM0zveAO8O5cUyF3tnAAAAAASUVORK5CYII=\");\n}\n.ui-icon-location:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJlJREFUOMuV0TEOAVEUhtHXWYGh04pWzypYlJWIIENU1oQQdJKjucUL4+Er/7knr5iUXsIAO9xxwxb9VCrQxXvnIo6XYI0KbdSxbUrwHkdVtlWxXUvwFEedbOvEdizBVRzV6AbaxrYswanPTUqwhUMDOqD17ZfMGuAsfQs9PDL0QC/9EhYZnKdfwzCDw/RP2GOf/g1jjD59fwKZSi5HaePOlAAAAABJRU5ErkJggg==\");\n}\n.ui-icon-lock:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHFJREFUOMtjYEAD////Dwbiw0D8HYoPAXEgAz4AVND7HzfowqUpGKrgBxBnA7EAEPNB2T+gcv7YNB6GSmZjkcuByh3EpvE7VFIAixw/VO4rNo1ggMf/mPL/SQQ002gCxObkaDQGYlNyNDZAMf000iZUAdQHDgw3MuoHAAAAAElFTkSuQmCC\");\n}\n.ui-icon-mail:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAIVJREFUOMtjYKA7+P//fzQQf/xPPACpjQZp5AJiRSA+SoQmkBoFkB6QxqtArAXEzEDcAMR/sGgAidVD1WiD9DBAJb4CcQLU6VZAfB9J0z0gtoTKJUDV/mdAM3kB1Ol8QLwEivmgYguQFTJgcRbY6UiBpw0V+09II9zpyE4jViNBMAAa6Q4ARIAH2Rfeh/QAAAAASUVORK5CYII=\");\n}\n.ui-icon-minus:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABZJREFUOE9jYBgFuMF/MsFQ0jgKcAMA2lPfIe/W1fgAAAAASUVORK5CYII=\");\n}\n.ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJNJREFUOMtjYKA1+P//vxAQ5wLxXGIUMwGxKxCvAOIf/yEgB58GeSBuAOIH/1HBdyAWRFfMAcSRQLwbiP/9xw6WI2swBOIpQPzuP2Hggu5pMyCOBuJ6IF4CxCeA+C2aJpCzGYkNSWRX1JMSBSehmv4CsRwpGpdCNe4iNdIboBojSNUYAw0kdlI1mgPxZHLTpyE2OQBXFwcOWoyvmwAAAABJRU5ErkJggg==\");\n}\n.ui-icon-phone:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAALRJREFUOMtj+P//PxMQLwDiI0DMy0AsACqOAuKz/yHgGNGagQrfAPFqNM08xGj8BtWwBqr5NxCbEqPx9H8EWAXEHsQ6tRxJ4yVSAocf6k8YCCZFcyySxi9AbE6K5vlImj8AsTWavBYQc2PTyAbEu5E0/wDiFKicNTT0sScSoCAXEO/5jwouAfFypHg+ikszyOaF/zHBGiTNh/D5OQGI36JphqWwiYQCTACIK4D4HNTPr2HRBQChdFG//DBhowAAAABJRU5ErkJggg==\");\n}\n.ui-icon-plus:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAB5JREFUOMtjYMAC/qMBBmLBcNP4n0wwlDSOJgDcGgFPin6QGOaERAAAAABJRU5ErkJggg==\");\n}\n.ui-icon-power:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAANBJREFUOMtjYMAB/v//vxeIdzOQCv5DATEKQ4H4FhCbo2sEUrZAfBuIA9E1KQLxV6jaUCwaY6HcL0Ash6xxClRiNS6nApkboEITkTXehwoa49FoBhW6g6zxD1SQBY9GVqjQb2SNX6CCQkhiF4H4PBJfBKrmE7LGQ1DBBCQxJiBmROKnQtXsQ9aYCBV8AQphLFGlAsSvoWpikSWYkWx9A8QloIACYhMgLgfid1A5UGpiQjdVEIgP/scNQJr4caUeJmhk7wbi51C8C4ijkf1LEQAAs65tnfCMVk0AAAAASUVORK5CYII=\");\n}\n.ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJ9JREFUOMtjYKAm+P///1kg/gnEP6DsQiBmJ0YjNnAZiGUIafQDYi4g5gZiXyC+DtV8CcVmICcUhPEYxI+kuQAmKArEr6BYlIArQOA0TGA1kj9W4dHIA1XzDVnwB1SQG49GTAugQQ4Cvng0YnoJyCiCagQFAD8ezaiBCORwAPEVJM1+UD+BcAihuJNF0owCiEkxHNDkdQYUelB8gqrpGQBlvyiNmsjT4QAAAABJRU5ErkJggg==\");\n}\n.ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAM9JREFUOMtjYEAC////lwbiTiC+AsQ/gfgHEF8C4lYglkBSV4+sKRaIv/zHDT4BcSQQNwPxH5imGCD+B1WwCoitgJgNiq2BeC2aIX9AmiSB+DNUII8BBwDK7UfX2A7lrMGjqRmbjVegHEscmhqx+Bes8QeUw8ZACqBE42WoRmtSNbZBNa4lQq0vEDPDOJLQyAWBEjyaqqBqDiILRiAlgA1AbA/E3FDsCMRboHJ/gTgI3cQwIP6AJ8mB5IJxOUcMiJuA+Dw03X6BskFxKYasFgCG8ZXX6DfYhgAAAABJRU5ErkJggg==\");\n}\n.ui-icon-search:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAONJREFUOMuV0c8qhVEUhvFvcvKlMHBCUUwU5RpMlIm5UnIFOp2bMHEDiokLkJKpMpXO4Bg4MlAGLkDK3/AzWYPd195iDd/nfVbttasqBjU6OMcdetjFdFUazOJGfp6wlpNqDKI0wDrmsYzjyF+x1BS3E2k0s/gg+EkTnAXYKDyjjU+8o07BbYiLv9zgPjpzaXgR4UpBGsJLdMZSsBPhaUHsBO81wRQeAx5iMrl2Fx/BNnNbV/EchS884K3xn32M5+QFHCXCNy6xhevIrtAuXbCFGYwk2cSf5MLCVN6r/jMh72P4BxnPgmBrkPyTAAAAAElFTkSuQmCC\");\n}\n.ui-icon-shop:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE9JREFUOMtjYEAD////ZwfiKUD8Hog/QtnsDIQAVOE6IBYDYlEg3gDEk4nRCLJJDIkPMuADMRr/EyMGlyAF4NJoiUWtOTEaybZxVOOAaQQAmEocSjETvxYAAAAASUVORK5CYII=\");\n}\n.ui-icon-star:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJFJREFUOMtjYMAB/v//bwzCDKQCoKZZQDyTVE28QPwZiD8BMQ8pGtP/I0AaKRrPImk8g0tRAhB//U88AKmNh2nWAuKrRGi6AlKLbjMXEC/Ao2k+SA0uZyvj0aiML1Cy8GjMxKdxA1TRWyAOh+K3ULH1uDSxQCN8KxBLIolLAvE2IP4IUoNNowG+yAbJgdQwUAoAbN9GiH93pK4AAAAASUVORK5CYII=\");\n}\n.ui-icon-tag:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEFJREFUOMtj+I8dNDAQAv9xgwZiNZoBsQXRmpEUgTRZEW3zf+JAAzaNDaOaSYhjApoJJowGspIiFs3EaULTjKEJAH1ft8O6vRfvAAAAAElFTkSuQmCC\");\n}\n.ui-icon-user:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJdJREFUOMud0jsOQUEUgOEpJGxD0CpswAqUohStLYitiEJUEtHZgETJKjyiIqqb3E9D4nFdE399vuTkzITwFgqYIMEarRAT+l5L0YyBK5/NY+A5Ax5/oZrsUlTz4ND3BnmwglMGOqD8a91ZBpzGHKeB6xO6oB77lssnuMgbLKGDMbb3X/MowQYjtFF8oB724tuhG/zZ3/AGG1/AkN/xnJsAAAAASUVORK5CYII=\");\n}\n.ui-icon-video:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAExJREFUOMvF0csJACAMBNE0KGJHlqtpYjwJIvF70Lk/CFmR5wEByIxTwFtwhmq5M1HYrEUAR7CiI9iiN/D6VOs5uuGSNYdfbJkAJ98rtv7WyPB7sagAAAAASUVORK5CYII=\");\n}\n/* Alt icons */\n.ui-alt-icon.ui-icon-action:after,\n.ui-alt-icon .ui-icon-action:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAH1JREFUOMtjYCAOzAJiNgYywH8gPgbEkuRoBOFnQGyJLgjDDVBxNSBeDsQf0OR/AnEaAw5NdkD8BYuhWDXCAC8QvwDiH0BcB8TihJwKA/lA/BmIrQkFDrrG3UAcjhY4M5GiowGXxrl4QrcBWS26RiMiogWrRga6aSQFk68RAP5OVqWXKdm9AAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-alert:after,\n.ui-alt-icon .ui-icon-alert:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJZJREFUOMtjYMANvIHYi4FEwAbEt4D4JhCzkqKxFIj/Q3EpsZokgPgTksZPUDGCYAFUgxkQW0DZ8wlpMgfif1DFMPAfKmaGSxMjEJ9EciKyxv9QOUZsGhOQFP2HOtMKTSweXRMvED9HU4QNP4eqhYNuLIpMoH5GF++CaVID4l9YFJhjcSoI/wRiVZDGrUQ4ER1vZaA7AAA8nEl47CBNKgAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-arrow-d:after,\n.ui-alt-icon .ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADRJREFUOMtjYMAO/qNhosGoRko1NmBRSAg3kKO5gRybG8hxdgOhgGkgRxM2zQ0MJIIGfJoARZtMu19O4xgAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-arrow-d-l:after,\n.ui-alt-icon .ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAElJREFUOMtjYCAeNEAxSQCk4T8UN5CjiWjN2DTBNTaQo4kBh9UENTFgESRKEwOa5AFiNTHgUEhUCJKlCZ/GA4Tiiuo2UuRHnJoBqxder3inhF8AAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-arrow-d-r:after,\n.ui-alt-icon .ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEFJREFUOMtjYECABigmCYA0/IfiBnI0kaQZm0aaaW4gRzNMHUk2I8sT7ewDaHyS/ExQIzGa8YIDdLORLD8So+k/AHCSXq9v5cRTAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-arrow-l:after,\n.ui-alt-icon .ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADdJREFUOMtjYMANGhjIACBN/8nV9J9cTf/J1fSfXE2EMFmaKNNItlMpChyKooOiBEBRkiMqkQMAcwJMu8C5mgwAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-arrow-r:after,\n.ui-alt-icon .ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADVJREFUOMtjYMAPGhjIBP/J1fyfXM3/ydX8H5/m/yTiBnI1wjXTTWMDxYFD0+hooFuSw6kJAOa7TLvbyXpwAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-arrow-u:after,\n.ui-alt-icon .ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADVJREFUOMtjYMANGqCYJADS8B+KG8jRRLRmbJoIasanCadmYjRhaCZFE0FnoyskGoxqpEQjABQxTLu007KqAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-arrow-u-l:after,\n.ui-alt-icon .ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEVJREFUOMtjYGBg+E8EbmDAAsjSxECuJnwaDzAQAFS3kSQ/HiAnVGGSDcRqxiZIlGZcfmggJ8BoppkojeiaidaErBmuCQCtL16vpLfRlQAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-arrow-u-r:after,\n.ui-alt-icon .ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEVJREFUOMu9zzEOACAIA8A+nafxM12JFiwMNmGCCwDcMQBLKBqbQgWX8W8bRz9myCuYISN9GZ1zLRTn26g88YkYllHEMtpyql6v/pwMSQAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-audio:after,\n.ui-alt-icon .ui-icon-audio:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAANVJREFUOMuF0jFKg0EQhuHHXCBqL1ELCytzi5zAKgh2ViEgYhMwYCkWaXIUG/sU6YJaCBZewKRRiaAkzRTLun/+r5pvZ15mdhjKukniBh7RVaNb/Cb+BN9YYbQJWmUgHOE1ctdVUAqeoxfxHj7wgwOYJkAOzsJfhe+Fv1eAUrCFOb6wjR384aUOhHG8dcK/Y9lQr62qxKaOh1jgE03sxqjPMInCEvgUvh++H/4u7TwsgGe4iHg/FrWMpSnB+QEc4y1yl1V/HmZgO7r8G7GkQXbkDzhNC9aKZ1PDJ0JepAAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-back:after,\n.ui-alt-icon .ui-icon-back:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAItJREFUOMtjYMAEDQxkAJCm/+Rq+k+uJhD+A8Svgfg4EE8AYgdiNWLDZ4BYl5BmViCWBmIXIG4F4qdQ8U9ArE1K4HAB8Vqo3GZ8zsYGJKAaP5Ma6sLkamyEatxLrAZQQNUD8T+oRldCGhSBuBiI70I1gDSWEmMTchzeBGIPYp34DIiXArEvEDOhSwIAi9Qyp4aUzewAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-bars:after,\n.ui-alt-icon .ui-icon-bars:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAACZJREFUOMtjYBgIcBKI/5OIT4A0HidD41GGUT/SCJwh148nhoYfAe0YURTen2r1AAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-bullets:after,\n.ui-alt-icon .ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADVJREFUOMtjYBgIcBKIj6Px/xPAJxigmo4iaTxOhMajDKN+pBE4A3MzEp8oP55Ac/OJwelHAGSiQoVBqpe0AAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-calendar:after,\n.ui-alt-icon .ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADRJREFUOMtjZECAk0D8D4gtGbCDM0D8B4gtQBxGIP7PQAYYYhoZKLWRJDZFGkedismmTCMAvGkkB7PDw7MAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-camera:after,\n.ui-alt-icon .ui-icon-camera:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJxJREFUOMtjYKAiUAfiGiBugGIQWxWbQi4gzkRS+BSI/6Phx0jyWUDMCdK4GYtCQngTSOMfLBIPgXgCEPdB2ejyID0YggeAWBTqfJCzRID4IBZ1GAIGaM4HOcuQGI0sQPwLif8TiFmJtXETEn89EBsTo/EQkh8zoOwj2DT+xSL4CIj7oSH7GFeobiIjHkHOB6cC5JRDCGfAUg5ZAAAIx317SYGtJAAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-carat-d:after,\n.ui-alt-icon .ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHFJREFUOMvV0DEKAjEQQNF3GhXXbXW9f6+nkGVTqRfQJoFlIDHa+SFFmHkpwt+1w7Fjb8KmXLaYccepgc544lbwFa98anjCY7V3gQFLA0e0YF+GNdxEa5wCjmiofUDEXah0CDj1oNKYQcoPfdX4C/rYG6dgMtFQD5sUAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-carat-l:after,\n.ui-alt-icon .ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFBJREFUOMtjYMAPdIH4PBCrMJAA9ID4NRD/B+KnQKxKqiYQfg/ExuRoMiFG0xtSNenTTRNFGnFpNiUl7pA1fyBV82s0zWZ01/yY1PSKM5EDAGi5MtgV7LNzAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-carat-r:after,\n.ui-alt-icon .ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFpJREFUOMtjYMAE6kB8Hoi1GEgAGkD8HIj/A/FLINYmVqMZEH+AaiRZszk1Nb+iVLMOJZp1idX4kVRbLcjRZIlFkzYxmj6RGh0W5GgCATUgfkpOxMM0nyOUyAF53TLQiFLV2gAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-carat-u:after,\n.ui-alt-icon .ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAGZJREFUOMtjYKAB0IdikjW9gWI9UjX9h2KiNOuhaYLh1/g060EVwBS/h2JkzbrEaDIBYlMg/oBLsy4OTTCArvkVTPN5PJpwaT4HElQB4qd4NMGAGVTzY6geMFAFYmMiosoMWdMQAQBshTLV2RAbgQAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-check:after,\n.ui-alt-icon .ui-icon-check:after,\nhtml .ui-alt-icon.ui-btn.ui-checkbox-on:after,\nhtml .ui-alt-icon .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEtJREFUOMtjYKADaIBikkAjEP+HYqI1NyFpIlozNk0YGhugToKBZmI1wSSayNGEDzfgCzGiNRHyD1Eh2EaOJhjoIEcTDHSRo4loAAAMpkH3I7j13AAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-clock:after,\n.ui-alt-icon .ui-icon-clock:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAANhJREFUOMuNkmEKgkAQhYd+hRdI9CpZpwiETlERdICiDhMh0R2qf4ZdxArsT9rbeAtT7GIPPnTHebvjzIp8KwYbcAVPUoA1iMSjMXiAxsMdpC5TzYQt6IMuScCO32ptjtVJU7XZGRzVes6cGwiF/2RP0rIlamWMrYSNaFhem3HA2EXYuYb/4zIaTowFXFcd8euk3l+uhIK7JNKuIXNzc+KBwckfxhmfH0/E4TZsuU8L5pSgZ4OpugAZuxcQU95eXYDR744ph+u7cqXLZBVyuGZOFcnBUpdn9AYEHE/v8XhZcwAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-cloud:after,\n.ui-alt-icon .ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHZJREFUOMtjYBgMQBiIE4G4FkoLEaMpEog/A/F/JPwRiEPwabIF4r9ommD4NxCb49K4C4cmGP4HxK+A2B9ZkzsQfyOgEYZfwjRVEKkBhr8AMSdI41sSNYLwRpDGd2Ro/AnSWE6GxnUwf7pAI7yBCJwJxBz0T5cA6NleA+xgAXwAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-comment:after,\n.ui-alt-icon .ui-icon-comment:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEdJREFUOMtjYGBgCATil0D8n0j8Coj9GUjUBMMvGaEMkgETA5lgVCMBja/J0AeKe3AqICURvABiX3STYJINpDqBLE0MpGgCAMwXLfKbu8xgAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-delete:after,\n.ui-alt-icon .ui-icon-delete:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE1JREFUOMtjYECABijGBbDKgwT+Q3EDDk0Y8siC2DTjlMcm8R/Jaf/xGYxLwX8CriFacwO+kCNZE9kaG2jlP6JDlGB0kJ0AyE5yZCVyAIGUcaXrtLjcAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-edit:after,\n.ui-alt-icon .ui-icon-edit:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEVJREFUOMtjYCAeNEAxSQCk4T8UN5CrkSjNyM4j2lZsChtI0USS8/6TqnGQa1IgRxMIJJCjCQQWkKMJBA5ANSdAnU0UAAB60T1Uc0QS+gAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-eye:after,\n.ui-alt-icon .ui-icon-eye:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJtJREFUOMtjYBhowAjEUUB8EIi/QvEBqBgjLk0SUEX/cWCQnDi6JjkgvgdV8AOIs4FYAIj5oOwfULl7ULVgwA/E15FMzsbimhwk+etQPQyr0JwkAFV8EoiPIxmOrGYlExbT/yHR/5ACDQOgOzUXi5oCJPlrUL9jDZxcqIECUE0/sQUODIgTiI792KIDOQFEQg34AsUHoGKMA5s2AdHHPobWAPyKAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-forbidden:after,\n.ui-alt-icon .ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAM1JREFUOMuFkkEOgjAQRd9S2WMIZ1HDMVi48wzcAEO8DGHlxlOAiecgshA31M1vUptiJ2lC+3mdmT+F38iBK/AEPsAMPIBGWjDOwASYlTUBZQha9MMN2AMbrQPQSltcOPcyDUAaqKiS/gIy1JPNNETgTvoFGWFUXhqBj9J65J5RP0TgROdvZLkL/oO3OpvRnIzcIwIXzp5GmzZghg/f9V3746gisAFGYGfF0nkAndxL1FPhZFqAk39zqeGuPbkxBNnINNxels8qs3bLA/gCVFFewZEF7yYAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-forward:after,\n.ui-alt-icon .ui-icon-forward:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAItJREFUOMtjYCAONDCQCf6Tq/k/MZodgHgCEB8H4tdA/AdJI1bNekB8Bk0RNoyiURuIP0ElngJxKxC7ALE0ELPis20rVGItEHOSEjhfoJISpEYHTKMQqcG9D6qxkVSNblCN/4C4DohZSNFcBtUIMuAuEBcDsQKxmj2A+CZavBENmIDYD4iXAvEzXIoAgqYyqw9Yg9IAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-gear:after,\n.ui-alt-icon .ui-icon-gear:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAOBJREFUOMuFkkEKwkAMRae13arQXVGo6BFEUS8hiLgSQZcteABddOFJ3YjSA9SK1T/wK2EIGHjw2ySTTDLG6DYAL1CBvhbgC70BMxCCAwio99RzsHYPsEkfUIOCWlLQZ1nJilcGeCBSOovoa2J/FopKJUhBF7SpS/ruoCUHcRFtpUrFTPhzkBhOT96nqyR2nJjKp5BWK4meG2MThyzf2FZJ3Al9BqPmI3CGk7E92/YRPOm7Obs3C2V3Gm8wkXuMxQO4K60+xJ5j12lfxJh7ykWVE/9NwdL8sYQP3N6tpwV8AdaYR91UZ7PcAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-grid:after,\n.ui-alt-icon .ui-icon-grid:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEJJREFUOMtjYGBgOAnE/6H4OAMEIIudgIqdQRf7j4aJFiNb43EkzlGoImxiJ7CIkQeGUOCcIDIgqBc4Z4gJiCEcOADCDYeuTK+m9gAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-heart:after,\n.ui-alt-icon .ui-icon-heart:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJRJREFUOMud0D0OAUEYBuDHFVyEisYlaITYm1GtcAU99V5CSb+bWKEwkrVZ+/cmb/PNPJkvwydj7JHghAiD0CjMEsQYBWOGDK9St9hVzLNgXCoOm3r257WmZnDvAW9w7AEPMO0BJ9+fjTugWCFDXFuga7j7kwnSGpQWVyxngbwCPTDXkDWeBZRjqWWigHOsdMymDr0BP5J/6NqLuzwAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-home:after,\n.ui-alt-icon .ui-icon-home:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAADhJREFUOMtjYMANGqCYJADS8B+KG8jRRLRmbJoIasanCadmYjRhaCZFE1abidWEAaiikRS5YasRAHf0YqUlUKReAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-info:after,\n.ui-alt-icon .ui-icon-info:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJxJREFUOMul0ksKwkAQhOHvFga9hwTvIQS8TkSPZ4gX8QG6Stx0IA6TQLSgNtPzz6O6+dYGZ1zxDrc4YW1CBzzRT/iBKgd1ycYtymStG8ObiZtK7DLrdxTiT/1CH0UQaWGsHNiI5PoZOFd7/QW2P4AX0dylYC0m4jETTgrfsBoKVWYAcu6wT0+torlT0C0HDSqiuU0k94og6vHz4AMNCIcMUIkWVwAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-location:after,\n.ui-alt-icon .ui-icon-location:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJdJREFUOMuVkDEKwkAUBafzBG7sbCVtej2FHionEVGJIZVniqJouoA2T/jo+pMd+M3sm2bhlxxogA54AjWwYIAcuAOvr7sNxY2GRyAAU6CSO3lhp1EwLsg9vPCqUWZcJnfxwoNGFTBTVMvtvXAT+ZjPrb1wArSRqNWbSxkJS0YwB3oT9XKj2JlwSwKFCQsSOeuSWQHLf49vN4Q5LhENhvAAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-lock:after,\n.ui-alt-icon .ui-icon-lock:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAG5JREFUOMtjYMAEwUB8GIi/Q/EhIA5kIAB6gfg/DtyFS1MwVMEPIM4GYgEg5oOyf0Dl/LFpPAyVzMYilwOVO4hN43eopAAWOX6o3FdsGmF+wQWwyv8nEdNGowkQm5Oj0RiITcnR2ADF9NNIm1AFAP9Vd4ZWPhWFAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-mail:after,\n.ui-alt-icon .ui-icon-mail:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAIRJREFUOMtjYBgIEA3EH4H4P5H4I1QPAxcQKwLxUSI0gdQoQPUwXAViLSBmBuIGIP6DRQNIrB6qRhuqByzxFYgToE63AuL7SJruAbElVC4BqvY/A5rJC6DO4APiJVDMBxVbgKYWw1kwp8MAzGn/CWlEdjqy01AwI0w3qYCJ3MhnYhgyAAD7hUiBFf5JtwAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-minus:after,\n.ui-alt-icon .ui-icon-minus:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABZJREFUOMtjYBgFeMF/MvFQ0jgKcAAApTQ3yWkQbYUAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-navigation:after,\n.ui-alt-icon .ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJRJREFUOMtjYKADEALiXCCeS4xiJiB2BeIVQPwDiP8DcQ4+DfJA3ADED6CKYfg7EAuiK+YA4kgg3g3E/9A0wPByZA2GQDwFiN/hUIyMXdA9bQbE0UBcD8RLgPgEEL9F0wRyNiOxIYnsinpSouAkVNNfIJYjReNSqMZdpEZ6A1RjBKkaY6CBxE6qRnMgnkxu+jTEJgEAOtUv19DqMFAAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-phone:after,\n.ui-alt-icon .ui-icon-phone:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAALBJREFUOMtjYGBgYALiBUB8BIh5GUgAUUB8Foj/A/ExUjS/AeLVaJp5iNH4DaphDVTzbyA2JUbjaahGEF4FxB7EOrUcSeMlUgKHH+pPmOZgUjTHImn8AsTmpGiej6T5AxBbo8lrATE3No1sQLwbSfMPIE6GyllDQx9nIuEC4j1ImmEBthwpno/i0gyyeSGaZuR4BrEP4fNzAhC/RdMMS2ETCAWYABBXAPE5qJ9fw6ILAKJsPsK6IqZ8AAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-plus:after,\n.ui-alt-icon .ui-icon-plus:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAB1JREFUOMtjYMAO/qNhosFw0/ifTDyUNI4mABwaAYa6X6GPliIhAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-power:after,\n.ui-alt-icon .ui-icon-power:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAMZJREFUOMtjYMAN9gLxbgYywH8oJghCgfgWEJtj0WgLxLeBOBBdkyIQf4UqDMWiMRbK/gLEcsgap0AlVuNx6gYofyKyxvtQQWM8Gs2g/DvIGv9ABVnwaGSF8n8ja/wCFRRCErsIxOeR+CJQNZ+QNR6CCiYgiTEBMSMSPxWqZh+yxkSo4AtoCKMDFSB+DVUTiyzBjGTrGyAugQaUCRCXA/E7qNxeqEtQgCAQH0QKFHQM0sSPK/UwQZ0CSqPPoXgXEEej+Zd8AAA35kK6jnLDjgAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-recycle:after,\n.ui-alt-icon .ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJVJREFUOMtjYKAyOAvEP4H4B5RdCMTsxGj8jwVfBmIZQhr9gJgLiLmB2BeIr0M1X0K3ORSKcQF+JM0FMEFRIH4FxaIEXAHSeBomsBrJH6vwaOSBqvmGLPgDKsiNRyNWC85CBXzxaMTqpSKoxuvQgMAFMAKRA4ivIGn2g/oJhEMIxZ0skmZ0TBBwQJPXGWjogfAJqiZmAOozM3SzI/gZAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-refresh:after,\n.ui-alt-icon .ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAMlJREFUOMtjYEAF0kDcCcRXgPgnEP8A4ktA3ArEEkjq6pE1xQLxFyD+jwN/AuJIIG4G4j8wTTFA/A+qYBUQWwExGxRbA/FaNEPAGiWB+DNUII8BN9iPrrEdylmDR1MzNhuvQDmWODQ1YvEvWOMPKIeNgURAtsbLUI3WpGpsg2pcS4RaXyBmhnEkoZEL0lyCR1MVVM1BZMEIpASwAYjtgZgbih2BeAtU7i8QB6GbGAbEH/AkOZBcMC7niAFxExCfh6bbL1B2I1QODgBeWE0SXtioYgAAAABJRU5ErkJggg==\");\n}\n.ui-alt-icon.ui-icon-search:after,\n.ui-alt-icon .ui-icon-search:after,\n.ui-input-search:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAOZJREFUOMuV0U8rxFEUxvFPSjMUG/oRio2ivAZLG3ulZGsjzevwBpTZzAuYlD3Zi2JhZKEs7Aclf/Jvc3D7dX8TT906Pc/5nu49l1/VsYUjXOME25jUQ9O4xGfmPGA5B9XRiaYOVjCLReyF/4SFMriZQMOZwc3I98vBQQSrFc8YxRte4nY/ugpwvscObqJn5tvoQzfqiQqohiLqbgoeRt2oADcwgFPcp8E47uIqLYwl227gNbK13NQlPEbDO27xXPrPM4zk4Dm0E+ADx1jHRXjnseWs+jGFocQr/grnlMI7/qkCuxj8AkXLP4FD310vAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-shop:after,\n.ui-alt-icon .ui-icon-shop:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAFBJREFUOMtjYMAE7EA8BYjfA/FHKJsdXRETFo29QCwFxOpArALEMkDcw0AEANkkhsQHsT8Qo/E/MWKMeBTjA4zY/GiFRcyCpjYSBUY10kIjAHnuC0BW95IBAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-star:after,\n.ui-alt-icon .ui-icon-star:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAIlJREFUOMtjYMANjKGYZDALiGeSqokXiD8D8Scg5iFFYzoQ/4fiNFI0nkXSeAaXogQg/oqkkBAGqY2HadYC4qtEaLoCVYsCuIB4AR5N86FqsAJlPBqV8QVKFh6Nmfg0boAqegvE4VD8Fiq2HpcmFmiEbwViSSRxEHsbEH+EqsEABgQiOw2qhjIAAOvoP4EZPNvPAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-tag:after,\n.ui-alt-icon .ui-icon-tag:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAEFJREFUOMtjYGBg+I8FNzAQAf6Tqxmm0AyILUjRDFME0mRFis3/icBYNTeMaiYtjhsoSRgN5CZFdM1Ea0LWjKEJAJLwYwqDORsHAAAAAElFTkSuQmCC\");\n}\n.ui-alt-icon.ui-icon-user:after,\n.ui-alt-icon .ui-icon-user:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAJdJREFUOMtjYMAELEC8BIh/A/EJIPZlIBJkAfF/JPwPiO2J0XgUTSMIrydG4ycsGl8R0qSKRRPMuSr4NNbi0AjC1fg0KgPxGyyaXgKxIiHnrsGicRkxgWMExF+RNH0GYj1i43IHksaN+BRyAHE4EC8A4ovQVAPTCGJfAOJ5QBwKxOwwTYlA/AJPaKLj50Acz0CCBnRMnkYAFb5i4CiuUNsAAAAASUVORK5CYII=\");\n}\n.ui-alt-icon.ui-icon-video:after,\n.ui-alt-icon .ui-icon-video:after {\n\tbackground-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE1JREFUOMtjYBgIEAjEL4H4Pw78Coj9sWnEpwmGX6LpaWAgQhMMI2v6T6rGBmQ+sRob0A2iuUaynYoROK+I0PQCW3T4E4hLkCZfhgEHAMf2cCELnGdHAAAAAElFTkSuQmCC\");\n}\n/* Globals */\n/* Font\n-----------------------------------------------------------------------------------------------------------*/\nhtml {\n\tfont-size: 100%;\n}\nbody,\ninput,\nselect,\ntextarea,\nbutton,\n.ui-btn {\n\tfont-size: 1em;\n\tline-height: 1.3;\n\tfont-family: sans-serif /*{global-font-family}*/;\n}\nlegend,\n.ui-input-text input,\n.ui-input-search input {\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n/* Form labels (overrides font-weight bold in bars, and mini font-size) */\n.ui-mobile label,\ndiv.ui-controlgroup-label {\n\tfont-weight: normal;\n\tfont-size: 16px;\n}\n/* Separators\n-----------------------------------------------------------------------------------------------------------*/\n/* Field contain separator (< 28em) */\n.ui-field-contain {\n\tborder-bottom-color: #828282;\n\tborder-bottom-color: rgba(0,0,0,.15);\n\tborder-bottom-width: 1px;\n\tborder-bottom-style: solid;\n}\n/* Table opt-in classes: strokes between each row, and alternating row stripes */\n/* Classes table-stroke and table-stripe are deprecated in 1.4. */\n.table-stroke thead th,\n.table-stripe thead th,\n.table-stripe tbody tr:last-child {\n\tborder-bottom: 1px solid #d6d6d6; /* non-RGBA fallback */\n\tborder-bottom: 1px solid rgba(0,0,0,.1);\n}\n.table-stroke tbody th,\n.table-stroke tbody td {\n\tborder-bottom: 1px solid #e6e6e6; /* non-RGBA fallback  */\n\tborder-bottom: 1px solid rgba(0,0,0,.05);\n}\n.table-stripe.table-stroke tbody tr:last-child th,\n.table-stripe.table-stroke tbody tr:last-child td {\n\tborder-bottom: 0;\n}\n.table-stripe tbody tr:nth-child(odd) td,\n.table-stripe tbody tr:nth-child(odd) th {\n\tbackground-color: #eeeeee; /* non-RGBA fallback  */\n\tbackground-color: rgba(0,0,0,.04);\n}\n/* Buttons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn,\nlabel.ui-btn {\n\tfont-weight: bold;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-btn {\n\ttext-decoration: none !important;\n}\n.ui-btn-active {\n\tcursor: pointer;\n}\n/* Corner rounding\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-btn-corner-all deprecated in 1.4 */\n.ui-corner-all {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-blocks}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-blocks}*/;\n}\n/* Buttons */\n.ui-btn-corner-all,\n.ui-btn.ui-corner-all,\n/* Slider track */\n.ui-slider-track.ui-corner-all,\n/* Flipswitch */\n.ui-flipswitch.ui-corner-all,\n/* Count bubble */\n.ui-li-count {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-buttons}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-buttons}*/;\n}\n/* Icon-only buttons */\n.ui-btn-icon-notext.ui-btn-corner-all,\n.ui-btn-icon-notext.ui-corner-all {\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Radius clip workaround for cleaning up corner trapping */\n.ui-btn-corner-all,\n.ui-corner-all {\n\t-webkit-background-clip: padding;\n\tbackground-clip: padding-box;\n}\n/* Popup arrow */\n.ui-popup.ui-corner-all > .ui-popup-arrow-guide {\n\tleft: .6em /*{global-radii-blocks}*/;\n\tright: .6em /*{global-radii-blocks}*/;\n\ttop: .6em /*{global-radii-blocks}*/;\n\tbottom: .6em /*{global-radii-blocks}*/;\n}\n/* Shadow\n-----------------------------------------------------------------------------------------------------------*/\n.ui-shadow {\n\t-webkit-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\tbox-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\t\t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n}\n.ui-shadow-inset {\n\t-webkit-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\tbox-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n}\n.ui-overlay-shadow {\n\t-webkit-box-shadow: 0 0 12px \t\trgba(0,0,0,.6);\n\t-moz-box-shadow: 0 0 12px \t\t\trgba(0,0,0,.6);\n\tbox-shadow: 0 0 12px \t\t\t\trgba(0,0,0,.6);\n}\n/* Icons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.3) /*{global-icon-disc}*/;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Alt icons */\n.ui-alt-icon.ui-btn:after,\n.ui-alt-icon .ui-btn:after,\nhtml .ui-alt-icon.ui-checkbox-off:after,\nhtml .ui-alt-icon.ui-radio-off:after,\nhtml .ui-alt-icon .ui-checkbox-off:after,\nhtml .ui-alt-icon .ui-radio-off:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.15) /*{global-icon-disc}*/;\n}\n/* No disc */\n.ui-nodisc-icon.ui-btn:after,\n.ui-nodisc-icon .ui-btn:after {\n\tbackground-color: transparent;\n}\n/* Icon shadow */\n.ui-shadow-icon.ui-btn:after,\n.ui-shadow-icon .ui-btn:after {\n\t-webkit-box-shadow: 0 1px 0 \t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\t-moz-box-shadow: 0 1px 0 \t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\tbox-shadow: 0 1px 0 \t\t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n}\n/* Checkbox and radio */\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after,\n.ui-btn.ui-radio-off:after,\n.ui-btn.ui-radio-on:after {\n\tdisplay: block;\n\twidth: 18px;\n\theight: 18px;\n\tmargin: -9px 2px 0 2px;\n}\n.ui-checkbox-off:after,\n.ui-btn.ui-radio-off:after {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n}\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after {\n\t-webkit-border-radius: .1875em;\n\tborder-radius: .1875em;\n}\n.ui-btn.ui-checkbox-off:after {\n\tbackground-color: #666;\n\tbackground-color: rgba(0,0,0,.3);\n}\n.ui-radio .ui-btn.ui-radio-on:after {\n\tbackground-image: none;\n\tbackground-color: #fff;\n\twidth: 8px;\n\theight: 8px;\n\tborder-width: 5px;\n\tborder-style: solid; \n}\n.ui-alt-icon.ui-btn.ui-radio-on:after,\n.ui-alt-icon .ui-btn.ui-radio-on:after {\n\tbackground-color: #000;\n}\n/* Loader */\n.ui-icon-loading {\n\tbackground: url(images/ajax-loader.gif);\n\tbackground-size: 2.875em 2.875em;\n}\n/* Swatches */\n/* A\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-a,\n.ui-page-theme-a .ui-bar-inherit,\nhtml .ui-bar-a .ui-bar-inherit,\nhtml .ui-body-a .ui-bar-inherit,\nhtml body .ui-group-theme-a .ui-bar-inherit {\n\tbackground-color: \t\t\t#e9e9e9 /*{a-bar-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bar-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bar-color}*/;\n\ttext-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 0 /*{a-bar-shadow-radius}*/ \t#eee /*{a-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-a,\n.ui-page-theme-a,\n.ui-page-theme-a .ui-panel-wrapper {\n\tbackground-color: \t\t\t#f9f9f9 /*{a-page-background-color}*/;\n\tborder-color:\t \t\t#bbb /*{a-page-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-page-color}*/;\n\ttext-shadow: 0 /*{a-page-shadow-x}*/ 1px /*{a-page-shadow-y}*/ 0 /*{a-page-shadow-radius}*/ \t#f3f3f3 /*{a-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-a,\n.ui-page-theme-a .ui-body-inherit,\nhtml .ui-bar-a .ui-body-inherit,\nhtml .ui-body-a .ui-body-inherit,\nhtml body .ui-group-theme-a .ui-body-inherit,\nhtml .ui-panel-page-container-a {\n\tbackground-color: \t\t\t#fff /*{a-body-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-body-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-body-color}*/;\n\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ \t#f3f3f3 /*{a-body-shadow-color}*/;\n}\n.ui-body-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-a a,\nhtml .ui-bar-a a,\nhtml .ui-body-a a,\nhtml body .ui-group-theme-a a {\n\tcolor: #3388cc /*{a-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-a a:visited,\nhtml .ui-bar-a a:visited,\nhtml .ui-body-a a:visited,\nhtml body .ui-group-theme-a a:visited {\n    color: #3388cc /*{a-link-visited}*/;\n}\n.ui-page-theme-a a:hover,\nhtml .ui-bar-a a:hover,\nhtml .ui-body-a a:hover,\nhtml body .ui-group-theme-a a:hover {\n\tcolor: #005599 /*{a-link-hover}*/;\n}\n.ui-page-theme-a a:active,\nhtml .ui-bar-a a:active,\nhtml .ui-body-a a:active,\nhtml body .ui-group-theme-a a:active {\n\tcolor: #005599 /*{a-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-a .ui-btn,\nhtml .ui-bar-a .ui-btn,\nhtml .ui-body-a .ui-btn,\nhtml body .ui-group-theme-a .ui-btn,\nhtml head + body .ui-btn.ui-btn-a,\n/* Button visited */\n.ui-page-theme-a .ui-btn:visited,\nhtml .ui-bar-a .ui-btn:visited,\nhtml .ui-body-a .ui-btn:visited,\nhtml body .ui-group-theme-a .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-a:visited {\n\tbackground-color: \t\t\t#f6f6f6 /*{a-bup-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bup-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bup-color}*/;\n\ttext-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #f3f3f3 /*{a-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-a .ui-btn:hover,\nhtml .ui-bar-a .ui-btn:hover,\nhtml .ui-body-a .ui-btn:hover,\nhtml body .ui-group-theme-a .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-a:hover {\n\tbackground-color: \t\t\t#ededed /*{a-bhover-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bhover-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bhover-color}*/;\n\ttext-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #f3f3f3 /*{a-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-a .ui-btn:active,\nhtml .ui-bar-a .ui-btn:active,\nhtml .ui-body-a .ui-btn:active,\nhtml body .ui-group-theme-a .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-a:active {\n\tbackground-color: \t\t\t#e8e8e8 /*{a-bdown-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bdown-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bdown-color}*/;\n\ttext-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #f3f3f3 /*{a-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-a .ui-btn.ui-btn-active,\nhtml .ui-bar-a .ui-btn.ui-btn-active,\nhtml .ui-body-a .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-a .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-a.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-a .ui-checkbox-on:after,\nhtml .ui-bar-a .ui-checkbox-on:after,\nhtml .ui-body-a .ui-checkbox-on:after,\nhtml body .ui-group-theme-a .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-a:after,\n/* Active flipswitch background */\n.ui-page-theme-a .ui-flipswitch-active,\nhtml .ui-bar-a .ui-flipswitch-active,\nhtml .ui-body-a .ui-flipswitch-active,\nhtml body .ui-group-theme-a .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-a .ui-slider-track .ui-btn-active,\nhtml .ui-bar-a .ui-slider-track .ui-btn-active,\nhtml .ui-body-a .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-a .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-a .ui-btn-active {\n\tbackground-color: \t\t#3388cc /*{a-active-background-color}*/;\n\tborder-color:\t \t\t#3388cc /*{a-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{a-active-color}*/;\n\ttext-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #005599 /*{a-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-a .ui-radio-on:after,\nhtml .ui-bar-a .ui-radio-on:after,\nhtml .ui-body-a .ui-radio-on:after,\nhtml body .ui-group-theme-a .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-a:after {\n\tborder-color:\t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-a .ui-btn:focus,\nhtml .ui-bar-a .ui-btn:focus,\nhtml .ui-body-a .ui-btn:focus,\nhtml body .ui-group-theme-a .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-a:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-a .ui-focus,\nhtml .ui-bar-a .ui-focus,\nhtml .ui-body-a .ui-focus,\nhtml body .ui-group-theme-a .ui-focus,\nhtml head + body .ui-btn-a.ui-focus,\nhtml head + body .ui-body-a.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#3388cc /*{a-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#3388cc /*{a-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* B\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-b,\n.ui-page-theme-b .ui-bar-inherit,\nhtml .ui-bar-b .ui-bar-inherit,\nhtml .ui-body-b .ui-bar-inherit,\nhtml body .ui-group-theme-b .ui-bar-inherit {\n\tbackground-color: \t\t\t#1d1d1d /*{b-bar-background-color}*/;\n\tborder-color:\t \t\t#1b1b1b /*{b-bar-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bar-color}*/;\n\ttext-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 0 /*{b-bar-shadow-radius}*/ \t#111 /*{b-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-b,\n.ui-page-theme-b,\n.ui-page-theme-b .ui-panel-wrapper {\n\tbackground-color: \t\t\t#252525 /*{b-page-background-color}*/;\n\tborder-color:\t \t\t#454545 /*{b-page-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-page-color}*/;\n\ttext-shadow: 0 /*{b-page-shadow-x}*/ 1px /*{b-page-shadow-y}*/ 0 /*{b-page-shadow-radius}*/ \t#111 /*{b-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-b,\n.ui-page-theme-b .ui-body-inherit,\nhtml .ui-bar-b .ui-body-inherit,\nhtml .ui-body-b .ui-body-inherit,\nhtml body .ui-group-theme-b .ui-body-inherit,\nhtml .ui-panel-page-container-b {\n\tbackground-color: \t\t\t#2a2a2a /*{b-body-background-color}*/;\n\tborder-color:\t \t\t#1d1d1d /*{b-body-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-body-color}*/;\n\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ \t#111 /*{b-body-shadow-color}*/;\n}\n.ui-body-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-b a,\nhtml .ui-bar-b a,\nhtml .ui-body-b a,\nhtml body .ui-group-theme-b a {\n\tcolor: #22aadd /*{b-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-b a:visited,\nhtml .ui-bar-b a:visited,\nhtml .ui-body-b a:visited,\nhtml body .ui-group-theme-b a:visited {\n    color: #22aadd /*{b-link-visited}*/;\n}\n.ui-page-theme-b a:hover,\nhtml .ui-bar-b a:hover,\nhtml .ui-body-b a:hover,\nhtml body .ui-group-theme-b a:hover {\n\tcolor: #0088bb /*{b-link-hover}*/;\n}\n.ui-page-theme-b a:active,\nhtml .ui-bar-b a:active,\nhtml .ui-body-b a:active,\nhtml body .ui-group-theme-b a:active {\n\tcolor: #0088bb /*{b-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-b .ui-btn,\nhtml .ui-bar-b .ui-btn,\nhtml .ui-body-b .ui-btn,\nhtml body .ui-group-theme-b .ui-btn,\nhtml head + body .ui-btn.ui-btn-b,\n/* Button visited */\n.ui-page-theme-b .ui-btn:visited,\nhtml .ui-bar-b .ui-btn:visited,\nhtml .ui-body-b .ui-btn:visited,\nhtml body .ui-group-theme-b .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-b:visited {\n\tbackground-color: \t\t\t#333 /*{b-bup-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bup-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n\ttext-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #111 /*{b-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-b .ui-btn:hover,\nhtml .ui-bar-b .ui-btn:hover,\nhtml .ui-body-b .ui-btn:hover,\nhtml body .ui-group-theme-b .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-b:hover {\n\tbackground-color: \t\t\t#373737 /*{b-bhover-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bhover-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n\ttext-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #111 /*{b-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-b .ui-btn:active,\nhtml .ui-bar-b .ui-btn:active,\nhtml .ui-body-b .ui-btn:active,\nhtml body .ui-group-theme-b .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-b:active {\n\tbackground-color: \t\t\t#404040 /*{b-bdown-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bdown-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n\ttext-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #111 /*{b-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-b .ui-btn.ui-btn-active,\nhtml .ui-bar-b .ui-btn.ui-btn-active,\nhtml .ui-body-b .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-b .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-b.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-b .ui-checkbox-on:after,\nhtml .ui-bar-b .ui-checkbox-on:after,\nhtml .ui-body-b .ui-checkbox-on:after,\nhtml body .ui-group-theme-b .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-b:after,\n/* Active flipswitch background */\n.ui-page-theme-b .ui-flipswitch-active,\nhtml .ui-bar-b .ui-flipswitch-active,\nhtml .ui-body-b .ui-flipswitch-active,\nhtml body .ui-group-theme-b .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-b .ui-slider-track .ui-btn-active,\nhtml .ui-bar-b .ui-slider-track .ui-btn-active,\nhtml .ui-body-b .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-b .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-b .ui-btn-active {\n\tbackground-color: \t\t#22aadd /*{b-active-background-color}*/;\n\tborder-color:\t \t\t#22aadd /*{b-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-active-color}*/;\n\ttext-shadow: 0 /*{b-active-shadow-x}*/ 1px /*{b-active-shadow-y}*/ 0 /*{b-active-shadow-radius}*/ #0088bb /*{b-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-b .ui-radio-on:after,\nhtml .ui-bar-b .ui-radio-on:after,\nhtml .ui-body-b .ui-radio-on:after,\nhtml body .ui-group-theme-b .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-b:after {\n\tborder-color:\t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-b .ui-btn:focus,\nhtml .ui-bar-b .ui-btn:focus,\nhtml .ui-body-b .ui-btn:focus,\nhtml body .ui-group-theme-b .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-b:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-b .ui-focus,\nhtml .ui-bar-b .ui-focus,\nhtml .ui-body-b .ui-focus,\nhtml body .ui-group-theme-b .ui-focus,\nhtml head + body .ui-btn-b.ui-focus,\nhtml head + body .ui-body-b.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#22aadd /*{b-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#22aadd /*{b-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Structure */\n/* Disabled\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-disabled deprecated in 1.4. :disabled not supported by IE8 so we use [disabled] */\n.ui-disabled,\n.ui-state-disabled,\nbutton[disabled],\n.ui-select .ui-btn.ui-state-disabled {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n\tcursor: default !important;\n\tpointer-events: none;\n}\n/* Focus state outline\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn:focus,\n.ui-btn.ui-focus {\n\toutline: 0;\n}\n/* Unset box-shadow in browsers that don't do it right */\n.ui-noboxshadow .ui-shadow,\n.ui-noboxshadow .ui-shadow-inset,\n.ui-noboxshadow .ui-overlay-shadow,\n.ui-noboxshadow .ui-shadow-icon.ui-btn:after,\n.ui-noboxshadow .ui-shadow-icon .ui-btn:after,\n.ui-noboxshadow .ui-focus,\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow  input:focus,\n.ui-noboxshadow .ui-panel {\n\t-webkit-box-shadow: none !important;\n\t-moz-box-shadow: none !important;\n\tbox-shadow: none !important;\n}\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow .ui-focus {\n\toutline-width: 1px;\n\toutline-style: auto;\n}\n/* Some unsets */\n.ui-mobile,\n.ui-mobile body {\n\theight: 99.9%;\n}\n.ui-mobile fieldset,\n.ui-page {\n\tpadding: 0;\n\tmargin: 0;\n}\n.ui-mobile a img,\n.ui-mobile fieldset {\n\tborder-width: 0;\n}\n/* Fixes for fieldset issues on IE10 and FF (see #6077) */\n.ui-mobile fieldset {\n\tmin-width: 0;\n}\n@-moz-document url-prefix() {\n\t.ui-mobile fieldset {\n\t\tdisplay: table-column;\n\t\tvertical-align: middle;\n\t}\n}\n/* Viewport */\n.ui-mobile-viewport {\n\tmargin: 0;\n\toverflow-x: visible;\n\t-webkit-text-size-adjust: 100%;\n\t-ms-text-size-adjust:none;\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n/* Issue #2066 */\nbody.ui-mobile-viewport,\ndiv.ui-mobile-viewport {\n\toverflow-x: hidden;\n}\n/* \"page\" containers - full-screen views, one should always be in view post-pageload */\n.ui-mobile [data-role=page],\n.ui-mobile [data-role=dialog],\n.ui-page {\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 100%;\n\tposition: absolute;\n\tdisplay: none;\n\tborder: 0;\n}\n/* On ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */\n.ui-page {\n\toutline: none;\n}\n.ui-mobile .ui-page-active {\n\tdisplay: block;\n\toverflow: visible;\n\toverflow-x: hidden;\n}\n@media screen and (orientation: portrait) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 420px;\n\t}\n}\n@media screen and (orientation: landscape) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 300px;\n\t}\n}\n/* Fouc */\n.ui-mobile-rendering > * {\n\tvisibility: hidden;\n}\n/* Non-js content hiding */\n.ui-nojs {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Loading screen */\n.ui-loading .ui-loader {\n\tdisplay: block;\n}\n.ui-loader {\n\tdisplay: none;\n\tz-index: 9999999;\n\tposition: fixed;\n\ttop: 50%;\n\tleft: 50%;\n\tborder:0;\n}\n.ui-loader-default {\n\tbackground: none;\n\tfilter: Alpha(Opacity=18);\n\topacity: .18;\n\twidth: 2.875em;\n\theight: 2.875em;\n\tmargin-left: -1.4375em;\n\tmargin-top: -1.4375em;\n}\n.ui-loader-verbose {\n\twidth: 12.5em;\n\tfilter: Alpha(Opacity=88);\n\topacity: .88;\n\tbox-shadow: 0 1px 1px -1px #fff;\n\theight: auto;\n\tmargin-left: -6.875em;\n\tmargin-top: -2.6875em;\n\tpadding: .625em;\n}\n.ui-loader-default h1 {\n\tfont-size: 0;\n\twidth: 0;\n\theight: 0;\n\toverflow: hidden;\n}\n.ui-loader-verbose h1 {\n\tfont-size: 1em;\n\tmargin: 0;\n\ttext-align: center;\n}\n.ui-loader .ui-icon-loading {\n\tbackground-color: #000;\n\tdisplay: block;\n\tmargin: 0;\n\twidth: 2.75em;\n\theight: 2.75em;\n\tpadding: .0625em;\n\t-webkit-border-radius: 2.25em;\n\tborder-radius: 2.25em;\n}\n.ui-loader-verbose .ui-icon-loading {\n\tmargin: 0 auto .625em;\n\tfilter: Alpha(Opacity=75);\n\topacity: .75;\n}\n.ui-loader-textonly {\n\tpadding: .9375em;\n\tmargin-left: -7.1875em;\n}\n.ui-loader-textonly .ui-icon-loading {\n\tdisplay: none;\n}\n.ui-loader-fakefix {\n\tposition: absolute;\n}\n/* Headers, content panels */\n.ui-bar,\n.ui-body {\n\tposition: relative;\n\tpadding: .4em 1em;\n\toverflow: hidden;\n\tdisplay: block;\n\tclear: both;\n}\n.ui-bar h1,\n.ui-bar h2,\n.ui-bar h3,\n.ui-bar h4,\n.ui-bar h5,\n.ui-bar h6 {\n\tmargin: 0;\n\tpadding: 0;\n\tfont-size: 1em;\n\tdisplay: inline-block;\n}\n.ui-header,\n.ui-footer {\n\tborder-width: 1px 0;\n\tborder-style: solid;\n\tposition: relative;\n}\n.ui-header:empty,\n.ui-footer:empty {\n\tmin-height: 2.6875em;\n}\n.ui-header .ui-title,\n.ui-footer .ui-title {\n\tfont-size: 1em;\n\tmin-height: 1.1em;\n\ttext-align: center;\n\tdisplay: block;\n\tmargin: 0 30%;\n\tpadding: .7em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\toutline: 0 !important;\n}\n.ui-footer .ui-title {\n\tmargin: 0 1em;\n}\n.ui-content {\n\tborder-width: 0;\n\toverflow: visible;\n\toverflow-x: hidden;\n\tpadding: 1em;\n}\n/* Corner styling for dialogs and popups */\n.ui-corner-all > .ui-header:first-child,\n.ui-corner-all > .ui-content:first-child,\n.ui-corner-all > .ui-footer:first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-corner-all > .ui-header:last-child,\n.ui-corner-all > .ui-content:last-child,\n.ui-corner-all > .ui-footer:last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n/* Buttons and icons */\n.ui-btn {\n\tfont-size: 16px;\n\tmargin: .5em 0;\n\tpadding: .7em 1em;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: center;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\tcursor: pointer;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n.ui-btn-icon-notext,\n.ui-header button.ui-btn.ui-btn-icon-notext,\n.ui-footer button.ui-btn.ui-btn-icon-notext {\n\tpadding: 0;\n\twidth: 1.75em;\n\theight: 1.75em;\n\ttext-indent: -9999px;\n\twhite-space: nowrap !important;\n}\n.ui-mini {\n\tfont-size: 12.5px;\n}\n.ui-mini .ui-btn {\n\tfont-size: inherit;\n}\n/* Make buttons in toolbars default to mini and inline. */\n.ui-header .ui-btn,\n.ui-footer .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-header .ui-controlgroup .ui-btn-icon-notext,\n.ui-footer .ui-controlgroup .ui-btn-icon-notext {\n    font-size: 12.5px;\n}\n/* To ensure same top and left/right position when ui-btn-left/right are added to something other than buttons. */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right {\n\tfont-size: 12.5px;\n}\n.ui-mini.ui-btn-icon-notext,\n.ui-mini .ui-btn-icon-notext,\n.ui-header .ui-btn-icon-notext,\n.ui-footer .ui-btn-icon-notext {\n\tfont-size: 16px;\t\n\tpadding: 0;\n}\n.ui-btn-inline {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin-right: .625em;\n}\n.ui-btn-icon-left {\n\tpadding-left: 2.5em;\n}\n.ui-btn-icon-right {\n\tpadding-right: 2.5em;\n}\n.ui-btn-icon-top {\n\tpadding-top: 2.5em;\n}\n.ui-btn-icon-bottom {\n\tpadding-bottom: 2.5em;\n}\n.ui-header .ui-btn-icon-top,\n.ui-footer .ui-btn-icon-top,\n.ui-header .ui-btn-icon-bottom,\n.ui-footer .ui-btn-icon-bottom {\n\tpadding-left: .3125em;\n\tpadding-right: .3125em;\n}\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tcontent: \"\";\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 22px;\n\theight: 22px;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after {\n\ttop: 50%;\n\tmargin-top: -11px;\n}\n.ui-btn-icon-left:after {\n\tleft: .5625em;\n}\n.ui-btn-icon-right:after {\n\tright: .5625em;\n}\n.ui-mini.ui-btn-icon-left:after,\n.ui-mini .ui-btn-icon-left:after,\n.ui-header .ui-btn-icon-left:after,\n.ui-footer .ui-btn-icon-left:after {\n\tleft: .37em;\n}\n.ui-mini.ui-btn-icon-right:after,\n.ui-mini .ui-btn-icon-right:after,\n.ui-header .ui-btn-icon-right:after,\n.ui-footer .ui-btn-icon-right:after {\n\tright: .37em;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after {\n\tleft: 50%;\n\tmargin-left: -11px;\n}\n.ui-btn-icon-top:after {\n\ttop: .5625em;\n}\n.ui-btn-icon-bottom:after {\n\ttop: auto;\n\tbottom: .5625em;\n}\n/* Buttons in header position classes */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right,\n.ui-btn-left > [class*=\"ui-\"],\n.ui-btn-right > [class*=\"ui-\"] {\n\tmargin: 0;\n}\n.ui-btn-left,\n.ui-btn-right {\n\tposition: absolute;\n\ttop: .24em;\n}\n.ui-btn-left {\n\tleft: .4em;\n}\n.ui-btn-right {\n\tright: .4em;\n}\n.ui-btn-icon-notext.ui-btn-left {\n\ttop: .3125em;\n\tleft: .3125em;\n}\n.ui-btn-icon-notext.ui-btn-right {\n\ttop: .3125em;\n\tright: .3125em;\n}\n/* Button elements */\nbutton.ui-btn,\n.ui-controlgroup-controls button.ui-btn-icon-notext {\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\twidth: 100%;\n}\nbutton.ui-btn-inline,\n.ui-header button.ui-btn,\n.ui-footer button.ui-btn {\n\twidth: auto;\n}\n/* Firefox adds a 1px border in a button element. We negate this to make sure they have the same height as other buttons in controlgroups. */\nbutton.ui-btn::-moz-focus-inner {\n\tborder: 0;\n}\nbutton.ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn {\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n\twidth: 1.75em;\n}\n/* Form labels */\n.ui-mobile label,\n.ui-controlgroup-label {\n\tdisplay: block;\n\tmargin: 0 0 .4em;\n}\n/* Accessible content hiding */\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-hide-label > label,\n.ui-hide-label .ui-controlgroup-label,\n.ui-hide-label .ui-rangeslider label,\n.ui-hidden-accessible {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Used for hiding elements by the filterable widget. You can also use this class to hide list items or buttons in controlgroups; this ensures correct corner styling. */\n.ui-screen-hidden {\n\tdisplay: none !important;\n}\n/* Transitions originally inspired by those from jQtouch, nice work, folks */\n.ui-mobile-viewport-transitioning,\n.ui-mobile-viewport-transitioning .ui-page {\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n.ui-page-pre-in {\n\topacity: 0;\n}\n.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.out {\n\t-webkit-animation-timing-function: ease-in;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-timing-function: ease-in;\n\t-moz-animation-duration: 225ms;\n\tanimation-timing-function: ease-in;\n\tanimation-duration: 225ms;\n}\n@-webkit-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-moz-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-webkit-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@-moz-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n.fade.out {\n\topacity: 0;\n\t-webkit-animation-duration: 125ms;\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-duration: 125ms;\n\t-moz-animation-name: fadeout;\n\tanimation-duration: 125ms;\n\tanimation-name: fadeout;\n}\n.fade.in {\n\topacity: 1;\n\t-webkit-animation-duration: 225ms;\n\t-webkit-animation-name: fadein;\n\t-moz-animation-duration: 225ms;\n\t-moz-animation-name: fadein;\n\tanimation-duration: 225ms;\n\tanimation-name: fadein;\n}\n.pop {\n\t-webkit-transform-origin: 50% 50%;\n\t-moz-transform-origin: 50% 50%;\n\ttransform-origin: 50% 50%;\n}\n.pop.in {\n\t-webkit-transform: scale(1);\n\t-webkit-animation-name: popin;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: scale(1);\n\t-moz-animation-name: popin;\n\t-moz-animation-duration: 350ms;\n\ttransform: scale(1);\n\tanimation-name: popin;\n\tanimation-duration: 350ms;\n    opacity: 1;\n}\n.pop.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n\topacity: 0;\n}\n.pop.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n\tanimation-name: fadein;\n}\n.pop.out.reverse {\n\t-webkit-transform: scale(.8);\n\t-webkit-animation-name: popout;\n\t-moz-transform: scale(.8);\n\t-moz-animation-name: popout;\n\ttransform: scale(.8);\n\tanimation-name: popout;\n}\n@-webkit-keyframes popin {\n    from {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n}\n@-moz-keyframes popin {\n    from {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n}\n@keyframes popin {\n    from {\n        transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        transform: scale(1);\n        opacity: 1;\n    }\n}\n@-webkit-keyframes popout {\n    from {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@-moz-keyframes popout {\n    from {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@keyframes popout {\n    from {\n        transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        transform: scale(.8);\n        opacity: 0;\n    }\n}\n/* keyframes for slidein from sides */\n@-webkit-keyframes slideinfromright {\n    from { -webkit-transform: translate3d(100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromright {\n    from { -moz-transform: translateX(100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromright {\n    from { transform: translateX(100%); }\n    to { transform: translateX(0); }\n}\n@-webkit-keyframes slideinfromleft {\n    from { -webkit-transform: translate3d(-100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromleft {\n    from { -moz-transform: translateX(-100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromleft {\n    from { transform: translateX(-100%); }\n    to { transform: translateX(0); }\n}\n/* keyframes for slideout to sides */\n@-webkit-keyframes slideouttoleft {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(-100%,0,0); }\n}\n@-moz-keyframes slideouttoleft {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(-100%); }\n}\n@keyframes slideouttoleft {\n    from { transform: translateX(0); }\n    to { transform: translateX(-100%); }\n}\n@-webkit-keyframes slideouttoright {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(100%,0,0); }\n}\n@-moz-keyframes slideouttoright {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(100%); }\n}\n@keyframes slideouttoright {\n    from { transform: translateX(0); }\n    to { transform: translateX(100%); }\n}\n.slide.out, .slide.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.slide.out {\n\t-webkit-transform: translate3d(-100%,0,0);\n\t-webkit-animation-name: slideouttoleft;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n}\n.slide.in {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromright;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromright;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromright;\n}\n.slide.out.reverse {\n\t-webkit-transform: translate3d(100%,0,0);\n\t-webkit-animation-name: slideouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n}\n.slide.in.reverse {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromleft;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromleft;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromleft;\n}\n.slidefade.out {\n\t-webkit-transform: translateX(-100%);\n\t-webkit-animation-name: slideouttoleft;\n\t-webkit-animation-duration: 225ms;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\t-moz-animation-duration: 225ms;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n\tanimation-duration: 225ms;\n}\n.slidefade.in {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n.slidefade.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: slideouttoright;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n\tanimation-duration: 200ms;\n}\n.slidefade.in.reverse {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n/* slide down */\n.slidedown.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slidedown.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfromtop;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfromtop;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfromtop;\n\tanimation-duration: 250ms;\n}\n.slidedown.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slidedown.out.reverse {\n\t-webkit-transform: translateY(-100%);\n\t-webkit-animation-name: slideouttotop;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(-100%);\n\t-moz-animation-name: slideouttotop;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(-100%);\n\tanimation-name: slideouttotop;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfromtop {\n    from { -webkit-transform: translateY(-100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfromtop {\n    from { -moz-transform: translateY(-100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfromtop {\n    from { transform: translateY(-100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttotop {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(-100%); }\n}\n@-moz-keyframes slideouttotop {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(-100%); }\n}\n@keyframes slideouttotop {\n    from { transform: translateY(0); }\n    to { transform: translateY(-100%); }\n}\n/* slide up */\n.slideup.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slideup.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfrombottom;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfrombottom;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfrombottom;\n\tanimation-duration: 250ms;\n}\n.slideup.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slideup.out.reverse {\n\t-webkit-transform: translateY(100%);\n\t-webkit-animation-name: slideouttobottom;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(100%);\n\t-moz-animation-name: slideouttobottom;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(100%);\n\tanimation-name: slideouttobottom;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfrombottom {\n    from { -webkit-transform: translateY(100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfrombottom {\n    from { -moz-transform: translateY(100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfrombottom {\n    from { transform: translateY(100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttobottom {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(100%); }\n}\n@-moz-keyframes slideouttobottom {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(100%); }\n}\n@keyframes slideouttobottom {\n    from { transform: translateY(0); }\n    to { transform: translateY(100%); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-flip {\n\t-webkit-perspective: 1000;\n\t-moz-perspective: 1000;\n\tperspective: 1000;\n\tposition: absolute;\n}\n.flip {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\tbackface-visibility: hidden;\n\ttransform: translateX(0);\n}\n.flip.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 175ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 175ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 175ms;\n}\n.flip.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 225ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 225ms;\n}\n.flip.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.flip.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-turn {\n\t-webkit-perspective: 200px;\n\t-moz-perspective: 200px;\n\t-ms-perspective: 200px;\n\tperspective: 200px;\n\tposition: absolute;\n}\n.turn {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-webkit-transform-origin: 0;\n\t\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\t-moz-transform-origin: 0;\n\t\n\tbackface-visibility :hidden;\n\ttransform: translateX(0);\n\ttransform-origin: 0;\n}\n.turn.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 125ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 125ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 125ms;\n}\n.turn.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 250ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 250ms;\n\t\n}\n.turn.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.turn.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* flow transition */\n.flow {\n\t-webkit-transform-origin: 50% 30%;\n\t-webkit-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\t-moz-transform-origin: 50% 30%;\t\n\t-moz-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\ttransform-origin: 50% 30%;\t\n\tbox-shadow: 0 0 20px rgba(0,0,0,.4);\n}\n.ui-dialog.flow {\n\t-webkit-transform-origin: none;\n\t-webkit-box-shadow: none;\n\t-moz-transform-origin: none;\t\n\t-moz-box-shadow: none;\n\ttransform-origin: none;\t\n\tbox-shadow: none;\n}\n.flow.out {\n\t-webkit-transform: translateX(-100%) scale(.7);\n\t-webkit-animation-name: flowouttoleft;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(-100%) scale(.7);\n\t-moz-animation-name: flowouttoleft;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(-100%) scale(.7);\n\tanimation-name: flowouttoleft;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.in {\n\t-webkit-transform: translateX(0) scale(1);\n\t-webkit-animation-name: flowinfromright;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(0) scale(1);\n\t-moz-animation-name: flowinfromright;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(0) scale(1);\n\tanimation-name: flowinfromright;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: flowouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: flowouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: flowouttoright;\n}\n.flow.in.reverse {\n\t-webkit-animation-name: flowinfromleft;\n\t-moz-animation-name: flowinfromleft;\n\tanimation-name: flowinfromleft;\n}\n@-webkit-keyframes flowouttoleft {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(-100%) scale(.7); }\n}\n@-moz-keyframes flowouttoleft {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(-100%) scale(.7); }\n}\n@keyframes flowouttoleft {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(-100%) scale(.7); }\n}\n@-webkit-keyframes flowouttoright {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform:  translateX(100%) scale(.7); }\n}\n@-moz-keyframes flowouttoright {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(100%) scale(.7); }\n}\n@keyframes flowouttoright {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(100%) scale(.7); }\n}\n@-webkit-keyframes flowinfromleft {\n    0% { -webkit-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromleft {\n    0% { -moz-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromleft {\n    0% { transform: translateX(-100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n@-webkit-keyframes flowinfromright {\n    0% { -webkit-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromright {\n    0% { -moz-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromright {\n    0% { transform: translateX(100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n.ui-field-contain,\n.ui-mobile fieldset.ui-field-contain {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n\tclear: both;\n\tpadding: .8em 0;\n}\n.ui-field-contain > label ~ [class*=\"ui-\"],\n.ui-field-contain .ui-controlgroup-controls {\n\tmargin: 0;\n}\n.ui-field-contain:last-child {\n\tborder-bottom-width: 0;\n}\n@media (min-width: 28em) {\n\t.ui-field-contain,\n\t.ui-mobile fieldset.ui-field-contain {\n\t\tpadding: 0;\n\t\tmargin: 1em 0;\n\t\tborder-bottom-width: 0;\n\t}\n\t.ui-field-contain:before,\n\t.ui-field-contain:after {\n\t\tcontent: \"\";\n\t\tdisplay: table;\n\t}\n\t.ui-field-contain:after {\n\t\tclear: both;\n\t}\n\t.ui-field-contain > label,\n\t.ui-field-contain .ui-controlgroup-label,\n\t.ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: left;\n\t\twidth: 20%;\n\t\tmargin: .5em 2% 0 0;\n\t}\n\t.ui-popup .ui-field-contain > label,\n\t.ui-popup .ui-field-contain .ui-controlgroup-label,\n\t.ui-popup .ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: none;\n\t\twidth: auto;\n\t\tmargin: 0 0 .4em;\n\t}\n\t.ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: left;\n\t\twidth: 78%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t}\n\t/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n\t.ui-hide-label > label ~ [class*=\"ui-\"],\n\t.ui-hide-label .ui-controlgroup-controls,\n\t.ui-popup .ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-popup .ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: none;\n\t\twidth: 100%;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline {\n\t\twidth: auto;\n\t\tmargin-right: .625em;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline.ui-btn-icon-notext {\n\t\twidth: 1.75em;\n\t}\n}\n/* content configurations. */\n.ui-grid-a,\n.ui-grid-b,\n.ui-grid-c,\n.ui-grid-d,\n.ui-grid-solo {\n\toverflow: hidden;\n}\n.ui-block-a,\n.ui-block-b,\n.ui-block-c,\n.ui-block-d,\n.ui-block-e {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfloat: left;\n\tmin-height: 1px;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n/* force new row */\n.ui-block-a {\n\tclear: left;\n}\nul.ui-grid-a,\nul.ui-grid-b,\nul.ui-grid-c,\nul.ui-grid-d,\nul.ui-grid-solo,\nli.ui-block-a,\nli.ui-block-b,\nli.ui-block-c,\nli.ui-block-d,\nli.ui-block-e {\n\tmargin-left: 0;\n\tmargin-right: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n/* No margin in grids for 100% width button elements until we can use max-width: fill-available; */\n[class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: 0;\n\tmargin-left: 0;\n}\n[class*=\"ui-block-\"] > .ui-btn,\n[class*=\"ui-block-\"] > .ui-select,\n[class*=\"ui-block-\"] > .ui-checkbox,\n[class*=\"ui-block-\"] > .ui-radio,\n[class*=\"ui-block-\"] > button.ui-btn-inline,\n[class*=\"ui-block-\"] > button.ui-btn-icon-notext,\n.ui-header [class*=\"ui-block-\"] > button.ui-btn,\n.ui-footer [class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: .3125em;\n\tmargin-left: .3125em;\n}\n.ui-grid-a > .ui-block-a,\n.ui-grid-a > .ui-block-b {\n\t/* width: 49.95%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 50%;\n}\n.ui-grid-b > .ui-block-a,\n.ui-grid-b > .ui-block-b,\n.ui-grid-b > .ui-block-c {\n\t/* width: 33.25%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 33.333%;\n}\n.ui-grid-c > .ui-block-a,\n.ui-grid-c > .ui-block-b,\n.ui-grid-c > .ui-block-c,\n.ui-grid-c > .ui-block-d {\n\t/* width: 24.925%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 25%;\n}\n.ui-grid-d > .ui-block-a,\n.ui-grid-d > .ui-block-b,\n.ui-grid-d > .ui-block-c,\n.ui-grid-d > .ui-block-d,\n.ui-grid-d > .ui-block-e {\n\t/* width: 19.925%; IE7 */\n\twidth: 20%;\n}\n.ui-grid-solo > .ui-block-a {\n\twidth: 100%;\n\tfloat: none; \n}\n/* preset breakpoint to switch to stacked grid styles below 35em (560px) */\n@media (max-width: 35em) {\n\t.ui-responsive > .ui-block-a,\n\t.ui-responsive > .ui-block-b,\n\t.ui-responsive > .ui-block-c,\n\t.ui-responsive > .ui-block-d,\n\t.ui-responsive > .ui-block-e {\n\t\twidth: 100%; \n\t\tfloat: none; \n\t}\n}\n/* fixed page header & footer configuration */\n.ui-header-fixed,\n.ui-footer-fixed {\n\tleft: 0;\n\tright: 0;\n\twidth: 100%;\n\tposition: fixed;\n\tz-index: 1000;\n}\n.ui-header-fixed {\n\ttop: -1px;\n\tpadding-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden {\n\ttop: 0;\n\tpadding-top: 0;\n}\n.ui-header-fixed .ui-btn-left,\n.ui-header-fixed .ui-btn-right {\n\tmargin-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden .ui-btn-left,\n.ui-header-fixed.ui-fixed-hidden .ui-btn-right {\n\tmargin-top: 0;\n}\n.ui-footer-fixed {\n\tbottom: -1px;\n\tpadding-bottom: 1px;\n}\n.ui-footer-fixed.ui-fixed-hidden {\n\tbottom: 0;\n\tpadding-bottom: 0;\n}\n.ui-header-fullscreen,\n.ui-footer-fullscreen {\n\tfilter: Alpha(Opacity=90);\n\topacity: .9;\n}\n/* updatePagePadding() will update the padding to actual height of header and footer. */\n.ui-page-header-fixed {\n\tpadding-top: 2.8125em;\n}\n.ui-page-footer-fixed {\n\tpadding-bottom: 2.8125em;\n}\n.ui-page-header-fullscreen > .ui-content,\n.ui-page-footer-fullscreen > .ui-content {\n\tpadding: 0;\n}\n.ui-fixed-hidden {\n\tposition: absolute;\n}\n/* Tap toggle: hide external fixed footer. See issue #6604 */\n.ui-footer-fixed.ui-fixed-hidden {\n  display: none;\n}\n.ui-page .ui-footer-fixed.ui-fixed-hidden {\n  display: block\n}\n.ui-page-header-fullscreen .ui-fixed-hidden,\n.ui-page-footer-fullscreen .ui-fixed-hidden {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-header-fixed .ui-btn,\n.ui-footer-fixed .ui-btn { \n\tz-index: 10;\n}\n/* workarounds for other widgets */\n.ui-android-2x-fixed .ui-li-has-thumb {\n\t-webkit-transform: translate3d(0,0,0);\n}\n.ui-navbar {\n\tmax-width: 100%;\n}\n.ui-navbar ul:before,\n.ui-navbar ul:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-navbar ul:after {\n\tclear: both;\n}\n.ui-navbar ul {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n\tdisplay: block;\n\tborder: 0;\n\tmax-width: 100%;\n\toverflow: visible;\n}\n.ui-navbar li .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: block;\n\tmargin: 0;\n\tborder-right-width: 0;\n}\n.ui-header .ui-navbar li button.ui-btn,\n.ui-footer .ui-navbar li button.ui-btn {\n\tmargin: 0;\n\twidth: 100%;\n}\n.ui-navbar .ui-btn:focus {\n\tz-index: 1;\n}\n/* fixes gaps caused by subpixel problem */\n.ui-navbar li:last-child .ui-btn {\n\tmargin-right: -4px;\n}\n.ui-navbar li:last-child .ui-btn:after {\n\tmargin-right: 4px;\n}\n.ui-content .ui-navbar li:last-child .ui-btn,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: 0;\n}\n.ui-content .ui-navbar li:last-child .ui-btn:after,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after {\n\tmargin-right: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after {\n\tmargin-right: 1px;\n}\n.ui-navbar .ui-grid-duo .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-header .ui-navbar .ui-btn,\n.ui-footer .ui-navbar .ui-btn {\n\tborder-top-width: 0;\n\tborder-bottom-width: 0;\n}\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-header .ui-title ~ .ui-navbar .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n/* Hide the native input element */\n.ui-input-btn input {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tbackground: #fff;\n\tbackground: rgba(255,255,255,0);\n\tfilter: Alpha(Opacity=0);\n\topacity: .1;\n\tfont-size: 1px;\n\ttext-indent: -9999px;\n\tz-index: 2;\n}\n/* Fixes IE/WP filter alpha opacity bugs */\n.ui-input-btn.ui-state-disabled input {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible {\n\tmargin: 0 -1em;\n}\n.ui-collapsible-inset,\n.ui-collapsible-set {\n\tmargin: .5em 0;\n}\n.ui-collapsible-heading {\n\tdisplay: block;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n}\n.ui-collapsible-heading .ui-btn {\n\ttext-align: left;\n\tmargin: 0;\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n}\n.ui-collapsible-heading .ui-btn-icon-top,\n.ui-collapsible-heading .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-collapsible-inset .ui-collapsible-heading .ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-collapsible-collapsed + .ui-collapsible:not(.ui-collapsible-inset) > .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-collapsible-heading-status {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible-content {\n\tdisplay: block;\n\tmargin: 0;\t\n\tpadding: .5em 1em;\n}\n.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n\tborder-top-width: 0;\n\tborder-bottom-width: 1px;\n\tborder-style: solid;\n}\n.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 1px;\n\tborder-right-width: 1px;\n}\n.ui-collapsible-inset .ui-collapsible-content {\n\tmargin: 0;\n}\n.ui-collapsible-content-collapsed {\n\tdisplay: none;\n}\n.ui-collapsible-set > .ui-collapsible.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-collapsible-heading,\n.ui-collapsible-heading > .ui-btn {\n\t-webkit-border-radius: inherit;\t\n\tborder-radius: inherit;\t\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\t\n\tborder-top-left-radius: inherit;\t\t\n}\n.ui-collapsible-content,\n.ui-collapsible-set .ui-collapsible.ui-last-child {\n\t-webkit-border-bottom-right-radius: inherit;\t\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\t\n\tborder-bottom-left-radius: inherit;\t\t\n}\n.ui-collapsible-themed-content:not(.ui-collapsible-collapsed) > .ui-collapsible-heading {\n\t-webkit-border-bottom-right-radius: 0;\t\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\t\n\tborder-bottom-left-radius: 0;\t\t\n}\n.ui-collapsible-set .ui-collapsible {\n\tmargin: -1px -1em 0;\n}\n.ui-collapsible-set .ui-collapsible-inset {\n\tmargin: -1px 0 0;\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\tmargin-top: 0;\n}\n.ui-controlgroup,\nfieldset.ui-controlgroup {\n\tpadding: 0;\n\tmargin: .5em 0;\n}\n.ui-field-contain .ui-controlgroup,\n.ui-field-contain fieldset.ui-controlgroup {\n\tmargin: 0;\n}\n.ui-mini .ui-controlgroup-label {\n\tfont-size: 16px;\n}\n.ui-controlgroup.ui-mini .ui-btn-icon-notext,\n.ui-controlgroup .ui-mini.ui-btn-icon-notext {\n\tfont-size: inherit;\n}\n.ui-controlgroup-controls .ui-btn,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-select {\n\tmargin: 0;\n}\n.ui-controlgroup-controls .ui-btn:focus,\n.ui-controlgroup-controls .ui-btn.ui-focus {\n\tz-index: 1;\n}\n.ui-controlgroup-controls li {\n\tlist-style: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:before,\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tclear: both;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls li > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select {\n\tfloat: left;\n\tclear: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,\n.ui-controlgroup-controls .ui-btn-icon-notext {\n\twidth: auto;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext {\n\twidth: 1.5em;\n}\n .ui-controlgroup-controls .ui-btn-icon-notext {\n\theight: auto;\n\tpadding: .7em 1em;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-bottom-width: 1px;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn {\n\tborder-right-width: 0;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-right-width: 1px;\n}\n.ui-controlgroup-controls .ui-btn-corner-all,\n.ui-controlgroup-controls .ui-btn.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-controlgroup-controls,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-select,\n.ui-controlgroup-controls li {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-last-child {\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-controls a.ui-shadow:not(:focus),\n.ui-controlgroup-controls button.ui-shadow:not(:focus),\n.ui-controlgroup-controls div.ui-shadow:not(.ui-focus) {\n\t-moz-box-shadow: none;\n\t-webkit-box-shadow: none;\n\tbox-shadow: none;\n}\n/* Fixes legend not wrapping on IE10 */\n.ui-controlgroup-label legend {\n\tmax-width: 100%;\n}\n.ui-controlgroup-controls > label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-dialog {\n\t background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */\n}\n.ui-dialog-contain {\n\twidth: 92.5%;\n\tmax-width: 500px;\n\tmargin: 10% auto 1em auto;\n\tpadding: 0;\n\tposition: relative;\n\ttop: -1em;\n}\n.ui-dialog-contain > .ui-header, \n.ui-dialog-contain > .ui-content, \n.ui-dialog-contain > .ui-footer { \n\tdisplay: block;\n\tposition: relative; \n\twidth: auto;\n\tmargin: 0;\n}\n.ui-dialog-contain > .ui-header {\n\toverflow: hidden;\n\tz-index: 10; \n\tpadding: 0;\n\tborder-top-width: 0;\n}\n.ui-dialog-contain > .ui-footer {\n\tz-index: 10; \n\tpadding: 0 1em; \n\tborder-bottom-width: 0;\n}\n.ui-popup-open .ui-header-fixed,\n.ui-popup-open .ui-footer-fixed {\n\tposition: absolute !important; /* See issues #4816, #4844 and #4874 and popup.js */\n}\n.ui-popup-screen {\n\tbackground-image: url(\"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\"); /* Necessary to set some form of background to ensure element is clickable in IE6/7. While legacy IE won't understand the data-URI'd image, it ensures no additional requests occur in all other browsers with little overhead. */\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 1px;\n\tposition: absolute;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 1099;\n}\n.ui-popup-screen.in {\n\topacity: 0.5;\n\tfilter: Alpha(Opacity=50);\n}\n.ui-popup-screen.out {\n\topacity: 0;\n\tfilter: Alpha(Opacity=0);\n}\n.ui-popup-container {\n\tz-index: 1100;\n\tdisplay: inline-block;\n\tposition: absolute;\n\tpadding: 0;\n\toutline: 0;\n}\n.ui-popup {\n\tposition: relative;\n}\n.ui-popup.ui-body-inherit {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-hidden {\n\tleft: 0;\n\ttop: 0;\n\tposition: absolute !important;\n\tvisibility: hidden;\n}\n.ui-popup-truncate {\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-popup.ui-content,\n.ui-popup .ui-content {\n\toverflow: visible;\n}\n.ui-popup > .ui-header {\n\tborder-top-width: 0;\n}\n.ui-popup > .ui-footer {\n\tborder-bottom-width: 0;\n}\n.ui-popup > p,\n.ui-popup > h1,\n.ui-popup > h2,\n.ui-popup > h3,\n.ui-popup > h4,\n.ui-popup > h5,\n.ui-popup > h6 {\n\tmargin: .5em .4375em;\n}\n.ui-popup > span {\n\tdisplay: block;\n\tmargin: .5em .4375em;\n}\n.ui-popup-container .ui-content > p,\n.ui-popup-container .ui-content > h1,\n.ui-popup-container .ui-content > h2,\n.ui-popup-container .ui-content > h3,\n.ui-popup-container .ui-content > h4,\n.ui-popup-container .ui-content > h5,\n.ui-popup-container .ui-content > h6 {\n\tmargin: .5em 0;\n}\n.ui-popup-container .ui-content > span {\n\tmargin: 0;\n}\n.ui-popup-container .ui-content > p:first-child,\n.ui-popup-container .ui-content > h1:first-child,\n.ui-popup-container .ui-content > h2:first-child,\n.ui-popup-container .ui-content > h3:first-child,\n.ui-popup-container .ui-content > h4:first-child,\n.ui-popup-container .ui-content > h5:first-child,\n.ui-popup-container .ui-content > h6:first-child {\n\tmargin-top: 0;\n}\n.ui-popup-container .ui-content > p:last-child,\n.ui-popup-container .ui-content > h1:last-child,\n.ui-popup-container .ui-content > h2:last-child,\n.ui-popup-container .ui-content > h3:last-child,\n.ui-popup-container .ui-content > h4:last-child,\n.ui-popup-container .ui-content > h5:last-child,\n.ui-popup-container .ui-content > h6:last-child {\n\tmargin-bottom: 0;\n}\n.ui-popup > img {\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tvertical-align: middle;\n}\n.ui-popup:not(.ui-content) > img:only-child,\n.ui-popup:not(.ui-content) > .ui-btn-left:first-child + img:last-child,\n.ui-popup:not(.ui-content) > .ui-btn-right:first-child + img:last-child {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-popup iframe {\n\tvertical-align: middle;\n}\n.ui-popup > .ui-btn-left,\n.ui-popup > .ui-btn-right {\n\tposition: absolute; \n\ttop: -11px;\n\tmargin: 0;\n\tz-index: 1101;\n}\n.ui-popup > .ui-btn-left {\n\tleft: -11px;\n}\n.ui-popup > .ui-btn-right {\n\tright: -11px;\n}\n/* Dimensions related to the popup arrow\n-----------------------------------------------------------------------------------------------------------*/\n/* desired triangle height: 10px */\n/**\n * guide for the arrow - its width, height, and offset are theme-dependent and\n * should be expessed as left, right, top, bottom, so that the element bearing\n * such a class becomes stretched inside its parent position: relative element.\n * The left/top/right/bottom specified below should reflect the corresponding\n * border radii and so it leaves room for the shadow:\n *     ..--------------------..\n *   .\"        ^ top           \".\n *  /          v                 \\\n * |     +------------------+     |\n * |     |                  |     |\n * | left|                  |right|\n * |<--->|                  |<--->|\n * |     +------------------+     |\n *  \\          ^                 /\n *   `.        v bottom        .'\n *     \"\"--------------------\"\"\n * The idea is that the top/left of the arrow container box does not move to a\n * coordinate smaller than the top/left of the guide and the right/bottom of\n * the arrow container box does not move to a coordinate larger than the\n * bottom/right of the guide. This will help us avoid the following situation:\n *        ..--------------------..\n *      .\"        ^ top           \".\n *   /|/          v                 \\\n *  / |     +------------------+     |\n *  \\ |     |                  |     |\n *   \\| left|                  |right|\n *    |<--->|                  |<--->|\n *    |     +------------------+     |\n *     \\          ^                 /\n *      `.        v bottom        .'\n *        \"\"--------------------\"\"\n * The arrow should not receive a top/left coordinate such that it is too close\n * to one of the corners, because then at first the shadow of the arrow and,\n * given a coordinate even closer to the corner, even the body of the arrow will\n * \"stick out\" of the corner of the popup. The guide provides a hint to the\n * arrow positioning code as to which range of values is acceptable for the\n * arrow container's top/left coordinate.\n **/\n.ui-popup-arrow-container {\n\twidth: 20px;\n\theight: 20px;\n}\n/* aside from the \"infinities\" (-1000,2000), triangle height is used */\n.ui-popup-arrow-container.ui-popup-arrow-l {\n\tleft: -10px;\n\tclip: rect(-1000px,10px,2000px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-t {\n\ttop: -10px;\n\tclip: rect(-1000px,2000px,10px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-r {\n\tright: -10px;\n\tclip: rect(-1000px,2000px,2000px,10px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-b {\n\tbottom: -10px;\n\tclip: rect(10px,2000px,1000px,-1000px);\n}\n/**\n * For each side, the arrow is twice the desired size and its corner is aligned\n * with the edge of the container:\n *                                           \n *           /\\         /\\                +----+       /\\\n *          /  \\       /  \\               | /\\ |top   /  \\\n *      +----+  \\     /  +----+       +-->|/  \\|     /    \\\n *  left| /  |   \\   /   |  \\ |right  |   |    |    /      \\\n *      |/   |    \\ /    |   \\|       |  /|    |\\  /        \\\n *      |\\   |    / \\    |   /|       | / +----+ \\ \\ +----+ /\n *      | \\  |   /   \\   |  / |       | \\        /  \\|    |/\n *      +----+  /     \\  +----+       |  \\      /    |    |\n *       ^  \\  /       \\  /  ^        |   \\    /  +->|\\  /|\n *       |   \\/         \\/   |        |    \\  /   |  | \\/ |bottom\n *       |                   |        |     \\/    |  +----+\n *       +-------------------+--------+-----------+\n *                           |\n *                    arrow container\n *                     (clips arrow)\n **/\n.ui-popup-arrow-container .ui-popup-arrow {\n\t/* (4*desired triangle height)/sqrt(2) - does not account for border - centred within the outer rectangle */\n\twidth: 28.284271247px;\n\theight: 28.284271247px;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: 5.857864376px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: -14.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow {\n\tleft: 5.857864376px;\n\ttop: -4.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow {\n\tleft: -14.142135623px;\n\ttop: -4.142135623px;\n}\n/* Fix rotation center for oldIE - see http://www.useragentman.com/IETransformsTranslator/ */\n.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -7.0710678118654755px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -4.142135623730951px;\n}\n \n.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow {\n    margin-left: -7.0710678118654755px;\n    margin-top: -5.857864376269049px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow {\n    margin-left: -4.142135623730951px;\n    margin-top: -5.857864376269049px;\n}\n/* structure */\n.ui-popup > .ui-popup-arrow-guide {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tvisibility: hidden;\n}\n.ui-popup-arrow-container {\n\tposition: absolute;\n}\n.ui-popup-arrow {\n\t-webkit-transform: rotate(45deg);\n\t-moz-transform: rotate(45deg);\n\t-ms-transform: rotate(45deg);\n\ttransform: rotate(45deg);\n\tposition: absolute;\n\toverflow: hidden;\n\tbox-sizing: border-box;\n}\n.ui-popup-arrow-container.ie .ui-popup-arrow {\n\t-ms-filter: \"progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod='auto expand')\";\n\tfilter: progid:DXImageTransform.Microsoft.Matrix(\n\t      \tM11=0.7071067811865474,\n        \tM12=-0.7071067811865477,\n        \tM21=0.7071067811865477,\n        \tM22=0.7071067811865474,\n        \tSizingMethod='auto expand');\n}\n.ui-checkbox,\n.ui-radio {\n\tmargin: .5em 0;\n\tposition: relative;\n}\n.ui-checkbox .ui-btn,\n.ui-radio .ui-btn {\n\tmargin: 0;\n\ttext-align: left;\n\twhite-space: normal; /* Nowrap + ellipsis doesn't work on label. Issue #1419. */\n\tz-index: 2;\n}\n.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,\n.ui-controlgroup .ui-radio .ui-btn.ui-focus {\n\tz-index: 3;\n}\n.ui-checkbox .ui-btn-icon-top,\n.ui-radio .ui-btn-icon-top,\n.ui-checkbox .ui-btn-icon-bottom,\n.ui-radio .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,\n.ui-controlgroup-horizontal .ui-radio .ui-btn:after {\n\tcontent: none;\n\tdisplay: none;\n}\n/* Native input positioning */\n.ui-checkbox input,\n.ui-radio input {\n\tposition: absolute;\n\tleft: .466em;\n\ttop: 50%;\n\twidth: 22px;\n\theight: 22px;\n\tmargin: -11px 0 0 0;\n\toutline: 0 !important;\n\tz-index: 1;\n}\n.ui-controlgroup-horizontal .ui-checkbox input,\n.ui-controlgroup-horizontal .ui-radio input {\n\tleft: 50%;\n\tmargin-left: -9px;\n}\n.ui-checkbox input:disabled,\n.ui-radio input:disabled {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select {\n\tmargin-top: .5em;\n\tmargin-bottom: .5em; /* no shorthand for margin because it would override margin-right for inline selects */\n\tposition: relative;\n}\n.ui-select > select {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select .ui-btn {\n\tmargin: 0;\n\topacity: 1; /* Fixes #2588: When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select (including \"inherit\") without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */\n}\n.ui-select .ui-btn select {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 1.5em;\n\tmin-height: 100%;\n\theight: 3em;\n\tmax-height: 100%;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 2;\n}\n@-moz-document url-prefix() {\n\t.ui-select .ui-btn select {\n\t\topacity: 0.0001;\n\t}\n}\n/* Display none because of issues with IE/WP's filter alpha opacity */\n.ui-select .ui-state-disabled select {\n\tdisplay: none;\n}\n/* Because we add all classes of the select and option elements to the span... */ \n.ui-select span.ui-state-disabled {\n\tfilter: Alpha(Opacity=100);\n\topacity: 1;\n}\n.ui-select .ui-btn.ui-select-nativeonly {\n\tborder-radius: 0;\n\tborder: 0;\n}\n.ui-select .ui-btn.ui-select-nativeonly select {\n\topacity: 1;\n\ttext-indent: 0;\n\tdisplay: block;\n}\n/* ui-li-count is styled in the listview CSS. We set padding and offset here because select supports icon position while listview doesn't. */\n.ui-select .ui-li-has-count.ui-btn {\n\tpadding-right: 2.8125em;\n}\n.ui-select .ui-li-has-count.ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-select .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n/* We set the rules for the span as well to fix an issue on Chrome with text-overflow ellipsis for the button in combination with text-align center. */\n.ui-select .ui-btn > span:not(.ui-li-count) {\n\tdisplay: block;\n\ttext-overflow: ellipsis;\n\toverflow: hidden !important;\n\twhite-space: nowrap;\n}\n.ui-selectmenu.ui-popup {\n\tmin-width: 11em;\n}\n.ui-selectmenu .ui-dialog-contain {\n\toverflow: hidden;\n}\n.ui-selectmenu .ui-header {\n\tmargin: 0;\n\tpadding: 0;\n\tborder-width: 0;\n}\n.ui-selectmenu.ui-dialog .ui-header {\n\tz-index: 1;\n\tposition: relative;\n}\n.ui-selectmenu.ui-popup .ui-header {\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n}\n/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button.  this shim's content in there */\n.ui-selectmenu.ui-popup .ui-header h1:after {\n\tcontent: '.';\n\tvisibility: hidden;\n}\n.ui-selectmenu .ui-header .ui-title {\n\tmargin: 0 2.875em;\n}\n.ui-selectmenu.ui-dialog .ui-content {\n\toverflow: visible;\n\tz-index: 1;\n}\n.ui-selectmenu .ui-selectmenu-list {\n\tmargin: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-header:not(.ui-screen-hidden) + .ui-selectmenu-list {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-top-left-radius: 0;\n\tborder-top-left-radius: 0;\n}\n.ui-header.ui-screen-hidden + .ui-selectmenu-list li.ui-first-child .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-selectmenu .ui-btn.ui-li-divider {\n\tcursor: default;\n}\n.ui-selectmenu .ui-selectmenu-placeholder {\n\tdisplay: none;\n}\n.ui-listview,\n.ui-listview > li {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n.ui-content .ui-listview,\n.ui-panel-inner > .ui-listview {\n\tmargin: -1em;\n}\n.ui-content .ui-listview-inset,\n.ui-panel-inner > .ui-listview-inset {\n\tmargin: 1em 0;\n}\n.ui-collapsible-content > .ui-listview {\n\tmargin: -.5em -1em;\n}\n.ui-collapsible-content > .ui-listview-inset {\n\tmargin: .5em 0;\n}\n.ui-listview > li {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tmargin: 0;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: left;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li > .ui-btn:focus {\n\tz-index: 1;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tborder-width: 1px 0 0 0;\n\tborder-style: solid;\n}\n.ui-listview-inset > .ui-li-static,\n.ui-listview-inset > .ui-li-divider,\n.ui-listview-inset > li > a.ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-listview > .ui-li-static.ui-last-child,\n.ui-listview > .ui-li-divider.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 1px;\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child,\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-listview > li.ui-first-child,\n.ui-listview > li.ui-first-child > a.ui-btn {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n}\n.ui-listview > li.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-listview > li.ui-li-has-alt > a.ui-btn {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n.ui-listview > li.ui-first-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-top-left-radius: 0;\t\n\tborder-top-left-radius: 0;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-listview > li.ui-last-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-listview > li.ui-first-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\t\n}\n.ui-listview > li.ui-last-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\t\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-listview > .ui-li-static {\n\tpadding: .7em 1em;\n}\n.ui-listview > .ui-li-divider {\n\tpadding: .5em 1.143em;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tcursor: default;\n\toutline: 0; /* Dividers in custom selectmenus have tabindex */\n}\n.ui-listview > .ui-li-has-count > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-count,\n.ui-listview > .ui-li-divider.ui-li-has-count {\n\tpadding-right: 2.8125em;\n}\n.ui-listview > .ui-li-has-count > .ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-listview > .ui-li-has-thumb > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-thumb {\n\tmin-height: 3.625em;\n\tpadding-left: 6.25em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-icon {\n\tmin-height: 1.25em;\n\tpadding-left: 2.5em;\n}\n/* Used by both listview and custom multiple select button */\n.ui-li-count {\n\tposition: absolute;\n\tfont-size: 12.5px;\n\tfont-weight: bold;\n\ttext-align: center;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tpadding: 0 .48em;\n\tline-height: 1.6em;\n\tmin-height: 1.6em;\n\tmin-width: .64em;\n\tright: .8em;\n\ttop: 50%;\n\tmargin-top: -.88em;\n}\n.ui-listview .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n.ui-listview .ui-li-has-thumb > img:first-child,\n.ui-listview .ui-li-has-thumb > .ui-btn > img:first-child,\n.ui-listview .ui-li-has-thumb .ui-li-thumb {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\tmax-height: 5em;\n\tmax-width: 5em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > img:first-child,\n.ui-listview > .ui-li-has-icon > .ui-btn > img:first-child {\n\tposition: absolute;\n\tleft: .625em;\n\ttop: .9em;\n\tmax-height: 1em;\n\tmax-width: 1em;\n}\n.ui-listview > li h1,\n.ui-listview > li h2,\n.ui-listview > li h3,\n.ui-listview > li h4,\n.ui-listview > li h5,\n.ui-listview > li h6 {\n\tfont-size: 1em;\n\tfont-weight: bold;\n\tdisplay: block;\n\tmargin: .45em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li p {\n\tfont-size: .75em;\n\tfont-weight: normal;\n\tdisplay: block;\n\tmargin: .6em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview .ui-li-aside {\n\tposition: absolute;\n\ttop: 1em;\n\tright: 3.333em;\n\tmargin: 0;\n\ttext-align: right;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn {\n\tmargin-right: 2.5em;\n\tborder-right-width: 0;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tposition: absolute;\n\twidth: 2.5em;\n\theight: 100%;\n\tmin-height: auto;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-left-width: 1px;\n\ttop: 0;\n\tright: 0;\n\tmargin: 0;\n\tpadding: 0;\n\tz-index: 2;\n}\n.ui-listview-inset > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tborder-right-width: 1px;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn:focus {\n\tz-index: 3;\n}\nol.ui-listview,\nol.ui-listview > .ui-li-divider {\n\tcounter-reset: listnumbering;\n}\nol.ui-listview > li > .ui-btn,\nol.ui-listview > li.ui-li-static {\n\tvertical-align: middle;\n}\nol.ui-listview > li > .ui-btn:first-child:before,\nol.ui-listview > li.ui-li-static:before,\nol.ui-listview > li.ui-field-contain > label:before,\nol.ui-listview > li.ui-field-contain > .ui-controlgroup-label:before {\n\tdisplay: inline-block;\n\tfont-size: .9em;\n\tfont-weight: normal;\n\tpadding-right: .3em;\n\tmin-width: 1.4em;\n\tline-height: 1.5;\n\tvertical-align: middle;\n\tcounter-increment: listnumbering;\n\tcontent: counter(listnumbering) \".\";\n}\nol.ui-listview > li.ui-field-contain:before {\n\tcontent: none;\n\tdisplay: none;\n}\nol.ui-listview > li h1:first-child,\nol.ui-listview > li h2:first-child,\nol.ui-listview > li h3:first-child,\nol.ui-listview > li h4:first-child,\nol.ui-listview > li h5:first-child,\nol.ui-listview > li h6:first-child,\nol.ui-listview > li p:first-child,\nol.ui-listview > li img:first-child + * {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\nol.ui-listview > li h1:first-child ~ *,\nol.ui-listview > li h2:first-child ~ *,\nol.ui-listview > li h3:first-child ~ *,\nol.ui-listview > li h4:first-child ~ *,\nol.ui-listview > li h5:first-child ~ *,\nol.ui-listview > li h6:first-child ~ *,\nol.ui-listview > li p:first-child ~ *,\nol.ui-listview > li img:first-child + * ~ * {\n\tmargin-top: 0;\n\ttext-indent: 2.04em; /* (1.4em + .3em) * .9em / .75em */\n}\nhtml .ui-filterable + .ui-listview,\nhtml .ui-filterable.ui-listview {\n\tmargin-top: .5em;\n}\n.ui-collapsible-content > form.ui-filterable {\n\tmargin-top: -.5em;\n}\n.ui-collapsible-content > .ui-input-search.ui-filterable {\n\tmargin-top: 0;\n}\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 1px;\n}\ndiv.ui-slider {\n\theight: 30px;\n\tmargin: .5em 0;\n\tpadding: 0;\n\t-ms-touch-action: pan-y pinch-zoom double-tap-zoom;\n}\ndiv.ui-slider:before,\ndiv.ui-slider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\ndiv.ui-slider:after {\n\tclear: both;\n}\ninput.ui-slider-input {\n\tdisplay: block;\n\tfloat: left;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tmargin: 0;\n\tpadding: 4px;\n\twidth: 40px;\n\theight: 20px;\n\tline-height: 20px;\n\tborder-width: 1px;\n\tborder-style: solid;\n\toutline: 0;\n\ttext-align: center;\n\tvertical-align: text-bottom;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tappearance: none;\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-slider-input::-webkit-outer-spin-button,\n.ui-slider-input::-webkit-inner-spin-button {\n\t-webkit-appearance: none;\n\tmargin: 0;\n}\n.ui-slider-track {\n\tposition: relative;\n\toverflow: visible;\n\tborder-width: 1px;\n\tborder-style: solid;\n\theight: 15px;\n\tmargin: 0 15px 0 68px;\n\ttop: 6px;\n}\n.ui-slider-track.ui-mini {\n\theight: 12px;\n\ttop: 8px;\n}\n.ui-slider-track .ui-slider-bg {\n\theight: 100%;\n}\n/* High level of specificity to override button margins in grids */\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tposition: absolute;\n\tz-index: 1;\n\ttop: 50%;\n\twidth: 28px;\n\theight: 28px;\n\tmargin: -15px 0 0 -15px;\n\toutline: 0;\n\tpadding: 0;\n}\n.ui-slider-track.ui-mini .ui-slider-handle {\n\theight: 14px;\n\twidth: 14px;\n\tmargin: -8px 0 0 -8px;\n}\nselect.ui-slider-switch {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\ndiv.ui-slider-switch {\n\tdisplay: inline-block;\n\theight: 32px;\n\twidth: 5.8em;\n\ttop: 0;\n}\n/* reset the clearfix */\ndiv.ui-slider-switch:before,\ndiv.ui-slider-switch:after {\n\tdisplay: none;\n\tclear: none;\n}\ndiv.ui-slider-switch.ui-mini {\n\theight: 29px;\n\ttop: 0;\n}\n.ui-slider-inneroffset {\n\tmargin: 0 16px;\n\tposition: relative;\n\tz-index: 1;\n}\n.ui-slider-switch.ui-mini .ui-slider-inneroffset {\n\tmargin: 0 15px 0 14px;\n}\n.ui-slider-switch .ui-btn.ui-slider-handle {\n\tmargin: 1px 0 0 -15px;\n}\n.ui-slider-switch.ui-mini .ui-slider-handle {\n\twidth: 25px;\n\theight: 25px;\n\tmargin: 1px 0 0 -13px;\n\tpadding: 0;\n}\n.ui-slider-handle-snapping {\n\t-webkit-transition: left 70ms linear;\n\t-moz-transition: left 70ms linear;\n\ttransition: left 70ms linear;\n}\n.ui-slider-switch .ui-slider-label {\n\tposition: absolute;\n\ttext-align: center;\n\twidth: 100%;\n\toverflow: hidden;\n\tfont-size: 16px;\n\ttop: 0;\n\tline-height: 2;\n\tmin-height: 100%;\n\twhite-space: nowrap;\n\tcursor: pointer;\n}\n.ui-slider-switch.ui-mini .ui-slider-label {\n\tfont-size: 14px;\n}\n.ui-slider-switch .ui-slider-label-a {\n\tz-index: 1;\n\tleft: 0;\n\ttext-indent: -1.5em;\n}\n.ui-slider-switch .ui-slider-label-b {\n\tz-index: 0;\n\tright: 0;\n\ttext-indent: 1.5em;\n}\n/* The corner radii for ui-slider-switch/track can be specified in theme CSS. The bg and handle inherits. */\n.ui-slider-track .ui-slider-bg,\n.ui-slider-switch .ui-slider-label,\n.ui-slider-switch .ui-slider-inneroffset,\n.ui-slider-handle {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-field-contain div.ui-slider-switch {\n\tmargin: 0;\n}\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-field-contain div.ui-slider-switch,\n.ui-field-contain.ui-hide-label div.ui-slider-switch,\nhtml .ui-popup .ui-field-contain div.ui-slider-switch {\n\tdisplay: inline-block;\n\twidth: 5.8em;\n}\n/* slider tooltip\n-----------------------------------------------------------------------------------------------------------*/\n.ui-slider-popup {\n\twidth: 64px;\n\theight: 64px;\n\tfont-size: 36px;\n\tpadding-top: 14px;\n\topacity: 0.8;\n}\n.ui-slider-popup {\n\tposition: absolute !important;\n\ttext-align: center;\n\tz-index: 100;\n}\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tfont-size: .9em;\n\tline-height: 30px;\n}\n.ui-rangeslider {\n\tmargin: .5em 0;\n}\n.ui-rangeslider:before,\n.ui-rangeslider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-rangeslider:after {\n\tclear: both;\n}\n.ui-rangeslider .ui-slider-input.ui-rangeslider-last {\n\tfloat: right;\n}\n.ui-rangeslider .ui-rangeslider-sliders {\n\tposition: relative;\n\toverflow: visible;\n\theight: 30px;\n\tmargin: 0 68px;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track {\n\tposition: absolute;\n\ttop: 6px;\n\tright: 0;\n\tleft: 0;\n\tmargin: 0;\n}\n.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track {\n\ttop: 8px;\n}\n.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg {\n\tdisplay: none;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\tbackground-color: transparent;\n\tbackground: none;\n\tborder-width: 0;\n\theight: 0;\n}\n/* this makes ie6 and ie7 set height to 0 to fix z-index problem */\nhtml >/**/body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 15px;\n\tborder-width: 1px;\n}\nhtml >/**/body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 12px;\n}\n/* Hide the second label (the first is moved outside the div) */\ndiv.ui-rangeslider label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-field-contain .ui-rangeslider input.ui-slider-input,\n.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,\n.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,\n.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders {\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n}\n.ui-input-text,\n.ui-input-search {\n\tmargin: .5em 0;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-mini {\n\tmargin: .446em;\n}\n.ui-input-text input,\n.ui-input-search input,\ntextarea.ui-input-text {\n\tpadding: .4em;\n\tline-height: 1.4em;\n\tdisplay: block;\n\twidth: 100%;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\toutline: 0;\n}\n.ui-input-text input,\n.ui-input-search input {\n\tmargin: 0;\n\tmin-height: 2.2em;\n\ttext-align: left; /* Opera aligns type=\"date\" right by default */\n\tborder: 0;\n\tbackground: transparent none;\n\t-webkit-appearance: none;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\ntextarea.ui-input-text {\n\toverflow: auto;\n\tresize: vertical;\n}\n.ui-mini .ui-input-text input,\n.ui-mini .ui-input-search input,\n.ui-input-text.ui-mini input,\n.ui-input-search.ui-mini input,\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tfont-size: 14px;\n}\n/* Same margin for mini textareas as other mini sized widgets (12.5/14 * 0.5em) */\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tmargin: .446em 0;\n}\n.ui-input-has-clear,\n.ui-input-search {\n\tposition: relative;\n}\n/* Padding on the div instead of input because of browser spinners etc. */\n.ui-input-has-clear {\n\tpadding-right: 2.375em;\n}\n.ui-mini.ui-input-has-clear {\n\tpadding-right: 2.923em;\n}\n.ui-input-has-clear input {\n\tpadding-right: 0;\n\t/* Autofill on Chrome has bg color so we unset corners right as well. */\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n/* Search icon */\n.ui-input-search input {\n\tpadding-left: 1.75em;\n}\n.ui-input-search:after {\n\tposition: absolute;\n\tleft: .3125em;\n\ttop: 50%;\n\tmargin-top: -7px;\n\tcontent: \"\";\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\twidth: 14px;\n\theight: 14px;\n\tfilter: Alpha(Opacity=50);\n\topacity: .5;\n}\n.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,\n.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear {\n\tposition: absolute;\n\tright: 0;\n\ttop: 50%;\n\tmargin: -14px .3125em 0;\n\tborder: 0;\n\tbackground-color: transparent;\n}\n.ui-input-search .ui-input-clear-hidden,\n.ui-input-text .ui-input-clear-hidden {\n\tdisplay: none;\n}\n/* Resolves issue #5166: Added to support issue introduced in Firefox 15. We can likely remove this in the future. */\n.ui-input-text input::-moz-placeholder,\n.ui-input-search input::-moz-placeholder,\ntextarea.ui-input-text::-moz-placeholder {\n\tcolor: #aaa;\n}\n/* Same for IE10 */\n.ui-input-text input:-ms-input-placeholder,\n.ui-input-search input:-ms-input-placeholder,\ntextarea.ui-input-text:-ms-input-placeholder {\n\tcolor: #aaa;\n}\n/* Resolves issue #5131: Width of textinput depends on its type,\nfor Android 4.1 */\n.ui-input-text input[type=number]::-webkit-outer-spin-button {\n\tmargin: 0;\n}\n/* Resolves issue #5756: Textinput in IE10 has a default clear button */\n.ui-input-text input::-ms-clear,\n.ui-input-search input::-ms-clear {\n\tdisplay: none;\n}\n.ui-input-text input:focus,\n.ui-input-search input:focus {\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n\tbox-shadow: none;\n}\ntextarea.ui-input-text.ui-textinput-autogrow {\n\toverflow: hidden;\n}\n.ui-textinput-autogrow-resize {\n\t-webkit-transition: height 0.25s;\n\t-o-transition: height 0.25s;\n\t-moz-transition: height 0.25s;\n\ttransition: height 0.25s;\n}\n.ui-flipswitch {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\twidth: 5.875em; /* Override this and padding-left in next rule if you use labels other than \"on/off\" and need more space */\n\theight: 1.875em;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tmargin: .5em 0;\n\toverflow: hidden;\n\t-webkit-transition-property: padding, width, background-color, color, border-color;\n\t-moz-transition-property: padding, width, background-color, color, border-color;\n\t-o-transition-property: padding, width, background-color, color, border-color;\n\ttransition-property: padding, width, background-color, color, border-color;\n\t-webkit-transition-duration: 100ms;\n\t-moz-transition-duration: 100ms;\n\t-o-transition-duration: 100ms;\n\ttransition-duration: 100ms;\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\tcursor: pointer;\n}\n.ui-flipswitch.ui-flipswitch-active {\n\tpadding-left: 4em;  /* Override this and width in previous rule if you use labels other than \"on/off\" and need more space */\n\twidth: 1.875em;\n}\n.ui-flipswitch-input {\n\tposition: absolute;\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n\tborder: 0;\n\toutline: 0;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on,\n.ui-flipswitch .ui-flipswitch-off {\n\tfloat: left;\n\theight: 1.75em;\n\tmargin: .0625em;\n\tline-height: 1.65em;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on {\n\twidth: 1.75em;\n\tpadding: 0;\n\ttext-indent: -2.6em; /* Override this to center text if you use a label other than \"on\" */\n\ttext-align: left;\n\tborder-width: 1px;\n\tborder-style: solid;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-radius: inherit;\n\toverflow: visible;\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n.ui-flipswitch .ui-flipswitch-off {\n\tpadding: 1px;\n\ttext-indent: 1em; /* Override this to center text if you use a label other than \"off\" */\n}\n/* Override field container CSS to prevent the flipswitch from becomming full width */\nhtml .ui-field-contain > label + .ui-flipswitch,\nhtml .ui-popup .ui-field-contain > label + .ui-flipswitch {\n\tdisplay: inline-block;\n\twidth: 5.875em; /* If you override the width for .ui-flipswitch you should repeat the same value here */\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-field-contain .ui-flipswitch.ui-flipswitch-active,\n.ui-popup .ui-field-contain .ui-flipswitch.ui-flipswitch-active {\n\twidth: 1.875em;\n}\n.ui-table {\n\tborder: 0;\n\tborder-collapse: collapse;\n\tpadding: 0;\n\twidth: 100%;\n}\n.ui-table th,\n.ui-table td {\n\tline-height: 1.5em;\n\ttext-align: left;\n\tpadding: .4em .5em;\n\tvertical-align:top;\n}\n.ui-table th .ui-btn,\n.ui-table td .ui-btn {\n\tline-height: normal;\n}\n.ui-table th {\n\tfont-weight: bold;\n}\n.ui-table caption {\n\ttext-align: left;\n\tmargin-bottom: 1.4em;\n\topacity: .5;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-columntoggle-btn {\n\tfloat: right;\n\tmargin-bottom: .8em;\n}\n/* Remove top/bottom margins around the fieldcontain on check list */\n.ui-table-columntoggle-popup fieldset {\n\tmargin:0;\n}\n.ui-table-columntoggle {\n\tclear: both;\n}\n/* Hide all prioritized columns by default */\n@media only all {\n\tth.ui-table-priority-6,\n\ttd.ui-table-priority-6,\n\tth.ui-table-priority-5,\n\ttd.ui-table-priority-5,\n\tth.ui-table-priority-4,\n\ttd.ui-table-priority-4,\n\tth.ui-table-priority-3,\n\ttd.ui-table-priority-3,\n\tth.ui-table-priority-2,\n\ttd.ui-table-priority-2,\n\tth.ui-table-priority-1,\n\ttd.ui-table-priority-1 {\n\t\tdisplay: none;\n\t}\n}\n/* Preset breakpoints if \".ui-responsive\" class added to table */\n/* Show priority 1 at 320px (20em x 16px) */\n@media screen and (min-width: 20em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-1 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 2 at 480px (30em x 16px) */\n@media screen and (min-width: 30em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-2 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 3 at 640px (40em x 16px) */\n@media screen and (min-width: 40em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-3 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 4 at 800px (50em x 16px) */\n@media screen and (min-width: 50em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-4 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 5 at 960px (60em x 16px) */\n@media screen and (min-width: 60em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-5 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 6 at 1,120px (70em x 16px) */\n@media screen and (min-width: 70em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-6 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Unchecked manually: Always hide */\n.ui-table-columntoggle th.ui-table-cell-hidden,\n.ui-table-columntoggle td.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden {\n\tdisplay: none;\n}\n/* Checked manually: Always show */\n.ui-table-columntoggle th.ui-table-cell-visible,\n.ui-table-columntoggle td.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible {\n\tdisplay: table-cell;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-reflow td .ui-table-cell-label,\n.ui-table-reflow th .ui-table-cell-label { \n\tdisplay: none;\n}\n/* Mobile first styles: Begin with the stacked presentation at narrow widths */ \n@media only all {\n\t/* Hide the table headers */ \n\t.ui-table-reflow thead td, \n\t.ui-table-reflow thead th {\n\t\tdisplay: none;\n\t}\n\t/* Show the table cells as a block level element */ \n\t.ui-table-reflow td,\n\t.ui-table-reflow th { \n\t\ttext-align: left;\n\t\tdisplay: block;\n\t}\n\t/* Add a fair amount of top margin to visually separate each row when stacked */  \n\t.ui-table-reflow tbody th {\n\t\tmargin-top: 3em;\n\t}\n\t/* Make the label elements a percentage width */ \n\t.ui-table-reflow td .ui-table-cell-label,\n\t.ui-table-reflow th .ui-table-cell-label { \n\t\tpadding: .4em; \n\t\tmin-width: 30%; \n\t\tdisplay: inline-block;\n\t\tmargin: -.4em 1em -.4em -.4em;\n\t}\n\t/* For grouped headers, have a different style to visually separate the levels by classing the first label in each col group */ \n\t.ui-table-reflow th .ui-table-cell-label-top,\n\t.ui-table-reflow td .ui-table-cell-label-top {\n\t\tdisplay: block;\n\t\tpadding: .4em 0;\n\t\tmargin: .4em 0;\n\t\ttext-transform: uppercase;\n\t\tfont-size: .9em;\n\t\tfont-weight: normal;\n\t}\n}\n/* Breakpoint to show as a standard table at 560px (35em x 16px) or wider */ \n@media ( min-width: 35em ) {\n\t/* Show the table header rows */ \n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th,\n\t.ui-table-reflow.ui-responsive tbody th,\n\t.ui-table-reflow.ui-responsive tbody td,\n\t.ui-table-reflow.ui-responsive thead td,\n\t.ui-table-reflow.ui-responsive thead th {\n\t\tdisplay: table-cell;\n\t\tmargin: 0;\n\t}\n\t/* Hide the labels in each cell */ \n\t.ui-table-reflow.ui-responsive td .ui-table-cell-label,\n\t.ui-table-reflow.ui-responsive th .ui-table-cell-label { \n\t\tdisplay: none;\n\t}\n}\n/* Hack to make IE9 and WP7.5 treat cells like block level elements, scoped to ui-responsive class */ \n/* Applied in a max-width media query up to the table layout breakpoint so we don't need to negate this*/ \n@media ( max-width: 35em ) {\n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th {\n\t\twidth: 100%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t\tfloat: left;\n\t\tclear: left;\n\t}\n}\n/* Panel */\n.ui-panel {\n\twidth: 17em;\n\tmin-height: 100%;\n\tmax-height: none;\n\tborder-width: 0;\n\tposition: absolute;\n\ttop: 0;\n\tdisplay: block;\n}\n.ui-panel-closed {\n\twidth: 0;\n\tmax-height: 100%;\n\toverflow: hidden;\n\tvisibility: hidden;\n\tleft: 0;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-panel-fixed {\n\tposition: fixed;\n\tbottom: -1px; /* Fixes gap on Chrome for Android */\n\tpadding-bottom: 1px;\n}\n.ui-panel-display-reveal {\n\tz-index: 1;\n}\n.ui-panel-display-push {\n\tz-index: 999;\n}\n.ui-panel-display-overlay {\n\tz-index: 1001; /* Fixed toolbars have z-index 1000 */\n}\n.ui-panel-inner {\n\tpadding: 1em;\n}\n/* Container, page and wrapper */\n.ui-panel-page-container {\n\toverflow-x: visible;\n}\n.ui-panel-page-container-themed .ui-page-active {\n\tbackground: none;\n}\n.ui-panel-wrapper {\n\tposition: relative;\n\tmin-height: inherit;\n\tborder: 0;\n\toverflow-x: hidden;\n\tz-index: 999;\n}\n/* Fixed toolbars */\n.ui-panel-fixed-toolbar {\n\toverflow-x: hidden;\n}\n/* Dismiss */\n.ui-panel-dismiss {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\theight: 100%;\n\tz-index: 1002;\n\tdisplay: none;\n}\n.ui-panel-dismiss-open {\n\tdisplay: block;\n}\n/* Animate class is added to panel, wrapper and fixed toolbars */\n.ui-panel-animate {\n\t-webkit-transition: -webkit-transform 300ms ease;\n\t-webkit-transition-duration: 300ms;\n\t-moz-transition: -moz-transform 300ms ease;\n\ttransition: transform 300ms ease;\n}\n/* Fix for Windows Phone issue #6349: unset the transition for transforms in case of fixed toolbars. */\n@media screen and ( max-device-width: 768px ) {\n\t.ui-page-header-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-page-footer-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: none;\n\t}\n\t/* We need a transitionend event ... */\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: -ms-transform 1ms;\n\t\t-ms-transform: rotate(0deg);\n\t}\n}\n/* Hardware acceleration for smoother transitions on WebKit browsers */\n.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal) {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translate3d(0,0,0);\n}\n/* Panel positioning (for overlay and push) */\n/* Panel left closed */\n.ui-panel-position-left {\n\tleft: -17em;\n}\n/* Panel left closed animated */\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-push {\n\tleft: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Panel left open */\n.ui-panel-position-left.ui-panel-display-reveal, /* Unset \"panel left closed\" for reveal */\n.ui-panel-open.ui-panel-position-left {\n\tleft: 0;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Panel right closed */\n.ui-panel-position-right {\n\tright: -17em;\n}\n/* Panel right closed animated */\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-push {\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-position-right.ui-panel-display-reveal, /* Unset \"panel right closed\" for reveal */\n.ui-panel-position-right.ui-panel-open {\n\tright: 0;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Wrapper and fixed toolbars positioning (for reveal and push) */\n/* Panel left open */\n.ui-panel-page-content-position-left {\n\tleft: 17em;\n\tright: -17em;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-page-content-position-left {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-page-content-position-right {\n\tleft: -17em;\n\tright: 17em;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-page-content-position-right {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Dismiss model open */\n.ui-panel-dismiss-open.ui-panel-dismiss-position-left {\n\tleft: 17em;\n}\n.ui-panel-dismiss-open.ui-panel-dismiss-position-right {\n\tright: 17em;\n}\n/* Shadows and borders */\n.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-display-overlay {\n\t-webkit-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-overlay {\n\t-webkit-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-panel-page-content-position-left.ui-panel-page-content-display-push {\n\tmargin-left: 1px;\n\twidth: auto;\n}\n.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\tborder-left-width: 1px;\n\tmargin-left: -1px;\n}\n.ui-panel-page-content-position-right.ui-panel-page-content-display-push {\n\tmargin-right: 1px;\n\twidth: auto;\n}\n/* Responsive: wrap on wide viewports once open */\n@media (min-width:55em) {\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left {\n\t\tmargin-right: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right {\n\t\tmargin-left: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open {\n\t\twidth: auto;\t\n\t}\n\t.ui-responsive-panel .ui-panel-dismiss-display-push,\n\t.ui-responsive-panel.ui-page-active ~ .ui-panel-dismiss-display-push {\n\t\tdisplay: none;\n\t}\n}\n.ui-tabs {\n\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n\tpadding: .2em;\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile.inline-svg-1.4.5.css",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n.ui-icon-action:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-alert:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8%20C6.447%2C8%2C6%2C7.553%2C6%2C7V5c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-audio:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-back:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-bars:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5%20C4.447%2C6%2C4%2C6.447%2C4%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1%20s0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6%20C0.447%2C6%2C0%2C6.447%2C0%2C7c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1%20S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-camera:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2%20v6c0%2C1.104%2C0.896%2C2%2C2%2C2h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2%20C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-check:after,\n/* Used ui-checkbox-on twice to increase specificity. If active state has background-image for gradient this rule overrides. */\nhtml .ui-btn.ui-checkbox-on.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-clock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2%20c-0.158%2C0-0.311%2C0.023-0.457%2C0.058C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9%20c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-comment:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-delete:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-edit:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-eye:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-forward:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-gear:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-grid:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-heart:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C1.872c-2-3-7-2-7%2C2c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.479%2C3%2C3c0.583-0.521%2C3-3%2C3-3s4-4%2C4-7%20C14-0.128%2C9-1.128%2C7%2C1.872z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-home:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-info:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-location:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4%20s0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-lock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848%20C6.207%2C9.673%2C6%2C9.366%2C6%2C9c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3%20s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-mail:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-minus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20style%3D%22fill%3A%23FFFFFF%3B%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-phone:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%22-0.01%200.008%2014%2014%22%20style%3D%22enable-background%3Anew%20-0.01%200.008%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M6.939%2C9.189C6.165%2C8.557%2C5.271%2C7.705%2C4.497%2C6.744C3.953%2C6.071%2C3.473%2C5.363%2C3.969%2C4.866l-3.482-3.48%20C-0.021%2C2.02-1.146%2C5.04%2C3.675%2C9.984c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.4C8.725%2C10.568%2C8.113%2C10.146%2C6.939%2C9.189z%20%20M13.82%2C11.519v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.211-0.546-0.205-0.754%2C0.002L9.455%2C9.831l3.403%2C3.407%20c0%2C0%2C0.962-0.96%2C0.961-0.961l0.002-0.001C14.043%2C12.056%2C14.021%2C11.721%2C13.82%2C11.519z%20M5.192%2C3.644V3.642%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.881c0%2C0-2.726-2.725-2.727-2.726C2.255-0.055%2C1.92-0.05%2C1.712%2C0.156L0.751%2C1.121l3.479%2C3.482%20C4.231%2C4.604%2C5.192%2C3.645%2C5.192%2C3.644z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-plus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-power:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455%20C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773%20C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773%20c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811%20C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1%20c-0.553%2C0-1%2C0.447-1%2C1v6C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11%20C4.791%2C11%2C3%2C9.209%2C3%2C7z%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4%20h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-search:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5%20s2.463%2C5.5%2C5.5%2C5.5c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-shop:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5%20S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5%20S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-star:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20style%3D%22fill%3A%23FFFFFF%3B%22%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-tag:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-user:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-icon-video:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20style%3D%22fill%3A%23FFFFFF%3B%22%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n/* Alt icons */\n.ui-alt-icon.ui-icon-action:after,\n.ui-alt-icon .ui-icon-action:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C12H2V5h1l2-2H0v11h13V7l-2%2C2V12z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-alert:after,\n.ui-alt-icon .ui-icon-alert:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8C6.447%2C8%2C6%2C7.553%2C6%2C7V5%20c0-0.553%2C0.447-1%2C1-1c0.553%2C0%2C1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d:after,\n.ui-alt-icon .ui-icon-arrow-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d-l:after,\n.ui-alt-icon .ui-icon-arrow-d-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-d-r:after,\n.ui-alt-icon .ui-icon-arrow-d-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-l:after,\n.ui-alt-icon .ui-icon-arrow-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-r:after,\n.ui-alt-icon .ui-icon-arrow-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u:after,\n.ui-alt-icon .ui-icon-arrow-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u-l:after,\n.ui-alt-icon .ui-icon-arrow-u-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-arrow-u-r:after,\n.ui-alt-icon .ui-icon-arrow-u-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-audio:after,\n.ui-alt-icon .ui-icon-audio:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-back:after,\n.ui-alt-icon .ui-icon-back:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C3V0L1%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C13%2C4%2C8%2C3%2C5%2C3z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-bars:after,\n.ui-alt-icon .ui-icon-bars:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C2%2C0%2C2.447%2C0%2C3S0.447%2C4%2C1%2C4z%20M13%2C6H1C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H1c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h12%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-bullets:after,\n.ui-alt-icon .ui-icon-bullets:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C4h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C2%2C4%2C2.447%2C4%2C3S4.447%2C4%2C5%2C4z%20M13%2C6H5C4.447%2C6%2C4%2C6.447%2C4%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1C14%2C6.447%2C13.553%2C6%2C13%2C6z%20M13%2C10H5c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1h8%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C10%2C13%2C10z%20M1%2C2C0.447%2C2%2C0%2C2.447%2C0%2C3s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C2%2C1%2C2z%20M1%2C6C0.447%2C6%2C0%2C6.447%2C0%2C7%20c0%2C0.553%2C0.447%2C1%2C1%2C1s1-0.447%2C1-1C2%2C6.447%2C1.553%2C6%2C1%2C6z%20M1%2C10c-0.553%2C0-1%2C0.447-1%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C10%2C1%2C10z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-calendar:after,\n.ui-alt-icon .ui-icon-calendar:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-camera:after,\n.ui-alt-icon .ui-icon-camera:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C2.5H9.908c-0.206-0.581-0.756-1-1.408-1h-3c-0.652%2C0-1.202%2C0.419-1.408%2C1H2c-1.104%2C0-2%2C0.896-2%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2%20h10c1.104%2C0%2C2-0.896%2C2-2v-6C14%2C3.396%2C13.104%2C2.5%2C12%2C2.5z%20M7%2C10.5c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C9.156%2C8.657%2C10.5%2C7%2C10.5z%20M7%2C5.5c-1.104%2C0-2%2C0.896-2%2C2c0%2C1.104%2C0.896%2C2%2C2%2C2c1.104%2C0%2C2-0.896%2C2-2C9%2C6.396%2C8.104%2C5.5%2C7%2C5.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-d:after,\n.ui-alt-icon .ui-icon-carat-d:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2211.949%2C3.404%207%2C8.354%202.05%2C3.404%20-0.071%2C5.525%207%2C12.596%2014.07%2C5.525%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-l:after,\n.ui-alt-icon .ui-icon-carat-l:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.596%2C11.949%205.646%2C7%2010.596%2C2.05%208.475%2C-0.071%201.404%2C7%208.475%2C14.07%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-r:after,\n.ui-alt-icon .ui-icon-carat-r:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%223.404%2C2.051%208.354%2C7%203.404%2C11.95%205.525%2C14.07%2012.596%2C7%205.525%2C-0.071%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-carat-u:after,\n.ui-alt-icon .ui-icon-carat-u:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%222.051%2C10.596%207%2C5.646%2011.95%2C10.596%2014.07%2C8.475%207%2C1.404%20-0.071%2C8.475%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-check:after,\n.ui-alt-icon .ui-icon-check:after,\nhtml .ui-alt-icon.ui-btn.ui-checkbox-on:after,\nhtml .ui-alt-icon .ui-btn.ui-checkbox-on:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C4%2011%2C1%205.003%2C6.997%203%2C5%200%2C8%204.966%2C13%204.983%2C12.982%205%2C13%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-clock:after,\n.ui-alt-icon .ui-icon-clock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-cloud:after,\n.ui-alt-icon .ui-icon-cloud:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14%2C9.5c0-0.793-0.465-1.473-1.134-1.795C12.949%2C7.484%2C13%2C7.249%2C13%2C7c0-1.104-0.896-2-2-2c-0.158%2C0-0.311%2C0.023-0.457%2C0.058%20C9.816%2C3.549%2C8.286%2C2.5%2C6.5%2C2.5c-2.33%2C0-4.224%2C1.777-4.454%2C4.046C0.883%2C6.76%2C0%2C7.773%2C0%2C9c0%2C1.381%2C1.119%2C2.5%2C2.5%2C2.5h10v-0.07%20C13.361%2C11.206%2C14%2C10.432%2C14%2C9.5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-comment:after,\n.ui-alt-icon .ui-icon-comment:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-delete:after,\n.ui-alt-icon .ui-icon-delete:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-edit:after,\n.ui-alt-icon .ui-icon-edit:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-eye:after,\n.ui-alt-icon .ui-icon-eye:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C2C3%2C2%2C0%2C7%2C0%2C7s3%2C5%2C7%2C5s7-5%2C7-5S11%2C2%2C7%2C2z%20M7%2C10c-1.657%2C0-3-1.344-3-3c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3%20C10%2C8.656%2C8.657%2C10%2C7%2C10z%20M7%2C6C6.448%2C6%2C6%2C6.447%2C6%2C7c0%2C0.553%2C0.448%2C1%2C1%2C1s1-0.447%2C1-1C8%2C6.447%2C7.552%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-forbidden:after,\n.ui-alt-icon .ui-icon-forbidden:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-forward:after,\n.ui-alt-icon .ui-icon-forward:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13%2C4L9%2C0v3C6%2C3%2C1%2C4%2C1%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L13%2C4z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-gear:after,\n.ui-alt-icon .ui-icon-gear:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-grid:after,\n.ui-alt-icon .ui-icon-grid:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-heart:after,\n.ui-alt-icon .ui-icon-heart:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C1.958c-2-3-7-2.128-7%2C1.872c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.48%2C3%2C3c0.583-0.52%2C3-3%2C3-3s4-4%2C4-7C14-0.169%2C9-1.042%2C7%2C1.958z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-home:after,\n.ui-alt-icon .ui-icon-home:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-info:after,\n.ui-alt-icon .ui-icon-info:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-location:after,\n.ui-alt-icon .ui-icon-location:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C4.791%2C0%2C3%2C1.791%2C3%2C4c0%2C2%2C4%2C10%2C4%2C10s4-8%2C4-10C11%2C1.791%2C9.209%2C0%2C7%2C0z%20M7%2C6C5.896%2C6%2C5%2C5.104%2C5%2C4s0.896-2%2C2-2%20c1.104%2C0%2C2%2C0.896%2C2%2C2S8.104%2C6%2C7%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-lock:after,\n.ui-alt-icon .ui-icon-lock:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C6V5c0-2.762-2.238-5-5-5C4.239%2C0%2C2%2C2.238%2C2%2C5v1H1v8h12V6H12z%20M7.5%2C9.848V12h-1V9.848C6.207%2C9.673%2C6%2C9.366%2C6%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C8%2C9.366%2C7.793%2C9.673%2C7.5%2C9.848z%20M10%2C6H4V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-mail:after,\n.ui-alt-icon .ui-icon-mail:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C3.75V12h14V3.75L7%2C9L0%2C3.75z%20M14%2C2H0l7%2C5L14%2C2z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-minus:after,\n.ui-alt-icon .ui-icon-minus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20y%3D%225%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-navigation:after,\n.ui-alt-icon .ui-icon-navigation:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2213%2C1%200%2C6%207%2C7%208%2C14%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-phone:after,\n.ui-alt-icon .ui-icon-phone:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M6.949%2C9.182C6.175%2C8.549%2C5.281%2C7.697%2C4.507%2C6.736C3.963%2C6.063%2C3.483%2C5.355%2C3.979%2C4.858l-3.482-3.48%20c-0.508%2C0.634-1.633%2C3.654%2C3.188%2C8.598c5.08%2C5.211%2C8.356%2C4.097%2C8.92%2C3.511l-3.396-3.399C8.734%2C10.561%2C8.123%2C10.139%2C6.949%2C9.182z%20%20M13.83%2C11.512v-0.004c0%2C0-2.648-2.646-2.649-2.647c-0.21-0.212-0.546-0.205-0.754%2C0.002L9.465%2C9.823l3.402%2C3.407%20c0%2C0%2C0.963-0.961%2C0.961-0.961l0.002-0.002C14.053%2C12.049%2C14.031%2C11.713%2C13.83%2C11.512z%20M5.202%2C3.636V3.634%20c0.222-0.222%2C0.2-0.557%2C0-0.758V2.873c0%2C0-2.726-2.725-2.727-2.726c-0.21-0.21-0.545-0.205-0.753%2C0.001L0.761%2C1.113L4.24%2C4.595%20C4.241%2C4.596%2C5.202%2C3.637%2C5.202%2C3.636z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-plus:after,\n.ui-alt-icon .ui-icon-plus:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-power:after,\n.ui-alt-icon .ui-icon-power:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11.243%2C2.408c-0.392-0.401-1.024-0.401-1.415%2C0c-0.391%2C0.401-0.391%2C1.054%2C0%2C1.455C10.584%2C4.642%2C11%2C5.675%2C11%2C6.773%20s-0.416%2C2.133-1.172%2C2.91c-1.512%2C1.558-4.145%2C1.558-5.656%2C0C3.416%2C8.904%2C3%2C7.872%2C3%2C6.773C3%2C5.673%2C3.416%2C4.64%2C4.172%2C3.863%20c0.39-0.401%2C0.39-1.054%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C1.624%2C3.574%2C1%2C5.125%2C1%2C6.773c0%2C1.647%2C0.624%2C3.199%2C1.757%2C4.365%20c1.134%2C1.166%2C2.64%2C1.809%2C4.243%2C1.809c1.604%2C0%2C3.109-0.645%2C4.243-1.811C12.376%2C9.975%2C13%2C8.423%2C13%2C6.773%20C13%2C5.125%2C12.376%2C3.574%2C11.243%2C2.408z%20M7%2C8.053c0.553%2C0%2C1-0.445%2C1-1v-6c0-0.553-0.447-1-1-1c-0.553%2C0-1%2C0.447-1%2C1v6%20C6%2C7.604%2C6.447%2C8.053%2C7%2C8.053z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-recycle:after,\n.ui-alt-icon .ui-icon-recycle:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C7h1L2%2C4L0%2C7h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.35v-2.205C8.41%2C10.789%2C7.732%2C11%2C7%2C11C4.791%2C11%2C3%2C9.209%2C3%2C7z%20%20M13%2C7c0-3.313-2.688-6-6-6C6.298%2C1%2C5.626%2C1.127%2C5%2C1.349v2.206C5.59%2C3.211%2C6.268%2C3%2C7%2C3c2.209%2C0%2C4%2C1.791%2C4%2C4h-1l2%2C3l2-3H13z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-refresh:after,\n.ui-alt-icon .ui-icon-refresh:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-search:after,\n.ui-alt-icon .ui-icon-search:after,\n.ui-input-search:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10.171%2C8.766c0.617-0.888%2C0.979-1.964%2C0.979-3.126c0-3.037-2.463-5.5-5.5-5.5s-5.5%2C2.463-5.5%2C5.5s2.463%2C5.5%2C5.5%2C5.5%20c1.152%2C0%2C2.223-0.355%2C3.104-0.962l3.684%2C3.683l1.414-1.414L10.171%2C8.766z%20M5.649%2C9.14c-1.933%2C0-3.5-1.567-3.5-3.5%20c0-1.933%2C1.567-3.5%2C3.5-3.5c1.933%2C0%2C3.5%2C1.567%2C3.5%2C3.5C9.149%2C7.572%2C7.582%2C9.14%2C5.649%2C9.14z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-shop:after,\n.ui-alt-icon .ui-icon-shop:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10%2C4V3c0-1.657-1.343-3-3-3S4%2C1.343%2C4%2C3v1H1v10h12V4H10z%20M4.5%2C6C4.224%2C6%2C4%2C5.776%2C4%2C5.5S4.224%2C5%2C4.5%2C5S5%2C5.224%2C5%2C5.5%20S4.776%2C6%2C4.5%2C6z%20M5%2C3c0-1.104%2C0.896-2%2C2-2c1.104%2C0%2C2%2C0.896%2C2%2C2v1H5V3z%20M9.5%2C6C9.225%2C6%2C9%2C5.776%2C9%2C5.5S9.225%2C5%2C9.5%2C5S10%2C5.224%2C10%2C5.5%20S9.775%2C6%2C9.5%2C6z%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-star:after,\n.ui-alt-icon .ui-icon-star:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-tag:after,\n.ui-alt-icon .ui-icon-tag:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-user:after,\n.ui-alt-icon .ui-icon-user:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\");\n}\n.ui-alt-icon.ui-icon-video:after,\n.ui-alt-icon .ui-icon-video:after {\n\tbackground-image: url(\"data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%20-2%2014%2014%22%20style%3D%22enable-background%3Anew%200%20-2%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3C%2Fsvg%3E\");\n}\n/* Globals */\n/* Font\n-----------------------------------------------------------------------------------------------------------*/\nhtml {\n\tfont-size: 100%;\n}\nbody,\ninput,\nselect,\ntextarea,\nbutton,\n.ui-btn {\n\tfont-size: 1em;\n\tline-height: 1.3;\n\tfont-family: sans-serif /*{global-font-family}*/;\n}\nlegend,\n.ui-input-text input,\n.ui-input-search input {\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n/* Form labels (overrides font-weight bold in bars, and mini font-size) */\n.ui-mobile label,\ndiv.ui-controlgroup-label {\n\tfont-weight: normal;\n\tfont-size: 16px;\n}\n/* Separators\n-----------------------------------------------------------------------------------------------------------*/\n/* Field contain separator (< 28em) */\n.ui-field-contain {\n\tborder-bottom-color: #828282;\n\tborder-bottom-color: rgba(0,0,0,.15);\n\tborder-bottom-width: 1px;\n\tborder-bottom-style: solid;\n}\n/* Table opt-in classes: strokes between each row, and alternating row stripes */\n/* Classes table-stroke and table-stripe are deprecated in 1.4. */\n.table-stroke thead th,\n.table-stripe thead th,\n.table-stripe tbody tr:last-child {\n\tborder-bottom: 1px solid #d6d6d6; /* non-RGBA fallback */\n\tborder-bottom: 1px solid rgba(0,0,0,.1);\n}\n.table-stroke tbody th,\n.table-stroke tbody td {\n\tborder-bottom: 1px solid #e6e6e6; /* non-RGBA fallback  */\n\tborder-bottom: 1px solid rgba(0,0,0,.05);\n}\n.table-stripe.table-stroke tbody tr:last-child th,\n.table-stripe.table-stroke tbody tr:last-child td {\n\tborder-bottom: 0;\n}\n.table-stripe tbody tr:nth-child(odd) td,\n.table-stripe tbody tr:nth-child(odd) th {\n\tbackground-color: #eeeeee; /* non-RGBA fallback  */\n\tbackground-color: rgba(0,0,0,.04);\n}\n/* Buttons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn,\nlabel.ui-btn {\n\tfont-weight: bold;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-btn {\n\ttext-decoration: none !important;\n}\n.ui-btn-active {\n\tcursor: pointer;\n}\n/* Corner rounding\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-btn-corner-all deprecated in 1.4 */\n.ui-corner-all {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-blocks}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-blocks}*/;\n}\n/* Buttons */\n.ui-btn-corner-all,\n.ui-btn.ui-corner-all,\n/* Slider track */\n.ui-slider-track.ui-corner-all,\n/* Flipswitch */\n.ui-flipswitch.ui-corner-all,\n/* Count bubble */\n.ui-li-count {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-buttons}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-buttons}*/;\n}\n/* Icon-only buttons */\n.ui-btn-icon-notext.ui-btn-corner-all,\n.ui-btn-icon-notext.ui-corner-all {\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Radius clip workaround for cleaning up corner trapping */\n.ui-btn-corner-all,\n.ui-corner-all {\n\t-webkit-background-clip: padding;\n\tbackground-clip: padding-box;\n}\n/* Popup arrow */\n.ui-popup.ui-corner-all > .ui-popup-arrow-guide {\n\tleft: .6em /*{global-radii-blocks}*/;\n\tright: .6em /*{global-radii-blocks}*/;\n\ttop: .6em /*{global-radii-blocks}*/;\n\tbottom: .6em /*{global-radii-blocks}*/;\n}\n/* Shadow\n-----------------------------------------------------------------------------------------------------------*/\n.ui-shadow {\n\t-webkit-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\tbox-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\t\t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n}\n.ui-shadow-inset {\n\t-webkit-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\tbox-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n}\n.ui-overlay-shadow {\n\t-webkit-box-shadow: 0 0 12px \t\trgba(0,0,0,.6);\n\t-moz-box-shadow: 0 0 12px \t\t\trgba(0,0,0,.6);\n\tbox-shadow: 0 0 12px \t\t\t\trgba(0,0,0,.6);\n}\n/* Icons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.3) /*{global-icon-disc}*/;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Alt icons */\n.ui-alt-icon.ui-btn:after,\n.ui-alt-icon .ui-btn:after,\nhtml .ui-alt-icon.ui-checkbox-off:after,\nhtml .ui-alt-icon.ui-radio-off:after,\nhtml .ui-alt-icon .ui-checkbox-off:after,\nhtml .ui-alt-icon .ui-radio-off:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.15) /*{global-icon-disc}*/;\n}\n/* No disc */\n.ui-nodisc-icon.ui-btn:after,\n.ui-nodisc-icon .ui-btn:after {\n\tbackground-color: transparent;\n}\n/* Icon shadow */\n.ui-shadow-icon.ui-btn:after,\n.ui-shadow-icon .ui-btn:after {\n\t-webkit-box-shadow: 0 1px 0 \t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\t-moz-box-shadow: 0 1px 0 \t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\tbox-shadow: 0 1px 0 \t\t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n}\n/* Checkbox and radio */\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after,\n.ui-btn.ui-radio-off:after,\n.ui-btn.ui-radio-on:after {\n\tdisplay: block;\n\twidth: 18px;\n\theight: 18px;\n\tmargin: -9px 2px 0 2px;\n}\n.ui-checkbox-off:after,\n.ui-btn.ui-radio-off:after {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n}\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after {\n\t-webkit-border-radius: .1875em;\n\tborder-radius: .1875em;\n}\n.ui-btn.ui-checkbox-off:after {\n\tbackground-color: #666;\n\tbackground-color: rgba(0,0,0,.3);\n}\n.ui-radio .ui-btn.ui-radio-on:after {\n\tbackground-image: none;\n\tbackground-color: #fff;\n\twidth: 8px;\n\theight: 8px;\n\tborder-width: 5px;\n\tborder-style: solid; \n}\n.ui-alt-icon.ui-btn.ui-radio-on:after,\n.ui-alt-icon .ui-btn.ui-radio-on:after {\n\tbackground-color: #000;\n}\n/* Loader */\n.ui-icon-loading {\n\tbackground: url(images/ajax-loader.gif);\n\tbackground-size: 2.875em 2.875em;\n}\n/* Swatches */\n/* A\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-a,\n.ui-page-theme-a .ui-bar-inherit,\nhtml .ui-bar-a .ui-bar-inherit,\nhtml .ui-body-a .ui-bar-inherit,\nhtml body .ui-group-theme-a .ui-bar-inherit {\n\tbackground-color: \t\t\t#e9e9e9 /*{a-bar-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bar-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bar-color}*/;\n\ttext-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 0 /*{a-bar-shadow-radius}*/ \t#eee /*{a-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-a,\n.ui-page-theme-a,\n.ui-page-theme-a .ui-panel-wrapper {\n\tbackground-color: \t\t\t#f9f9f9 /*{a-page-background-color}*/;\n\tborder-color:\t \t\t#bbb /*{a-page-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-page-color}*/;\n\ttext-shadow: 0 /*{a-page-shadow-x}*/ 1px /*{a-page-shadow-y}*/ 0 /*{a-page-shadow-radius}*/ \t#f3f3f3 /*{a-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-a,\n.ui-page-theme-a .ui-body-inherit,\nhtml .ui-bar-a .ui-body-inherit,\nhtml .ui-body-a .ui-body-inherit,\nhtml body .ui-group-theme-a .ui-body-inherit,\nhtml .ui-panel-page-container-a {\n\tbackground-color: \t\t\t#fff /*{a-body-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-body-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-body-color}*/;\n\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ \t#f3f3f3 /*{a-body-shadow-color}*/;\n}\n.ui-body-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-a a,\nhtml .ui-bar-a a,\nhtml .ui-body-a a,\nhtml body .ui-group-theme-a a {\n\tcolor: #3388cc /*{a-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-a a:visited,\nhtml .ui-bar-a a:visited,\nhtml .ui-body-a a:visited,\nhtml body .ui-group-theme-a a:visited {\n    color: #3388cc /*{a-link-visited}*/;\n}\n.ui-page-theme-a a:hover,\nhtml .ui-bar-a a:hover,\nhtml .ui-body-a a:hover,\nhtml body .ui-group-theme-a a:hover {\n\tcolor: #005599 /*{a-link-hover}*/;\n}\n.ui-page-theme-a a:active,\nhtml .ui-bar-a a:active,\nhtml .ui-body-a a:active,\nhtml body .ui-group-theme-a a:active {\n\tcolor: #005599 /*{a-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-a .ui-btn,\nhtml .ui-bar-a .ui-btn,\nhtml .ui-body-a .ui-btn,\nhtml body .ui-group-theme-a .ui-btn,\nhtml head + body .ui-btn.ui-btn-a,\n/* Button visited */\n.ui-page-theme-a .ui-btn:visited,\nhtml .ui-bar-a .ui-btn:visited,\nhtml .ui-body-a .ui-btn:visited,\nhtml body .ui-group-theme-a .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-a:visited {\n\tbackground-color: \t\t\t#f6f6f6 /*{a-bup-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bup-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bup-color}*/;\n\ttext-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #f3f3f3 /*{a-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-a .ui-btn:hover,\nhtml .ui-bar-a .ui-btn:hover,\nhtml .ui-body-a .ui-btn:hover,\nhtml body .ui-group-theme-a .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-a:hover {\n\tbackground-color: \t\t\t#ededed /*{a-bhover-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bhover-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bhover-color}*/;\n\ttext-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #f3f3f3 /*{a-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-a .ui-btn:active,\nhtml .ui-bar-a .ui-btn:active,\nhtml .ui-body-a .ui-btn:active,\nhtml body .ui-group-theme-a .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-a:active {\n\tbackground-color: \t\t\t#e8e8e8 /*{a-bdown-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bdown-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bdown-color}*/;\n\ttext-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #f3f3f3 /*{a-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-a .ui-btn.ui-btn-active,\nhtml .ui-bar-a .ui-btn.ui-btn-active,\nhtml .ui-body-a .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-a .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-a.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-a .ui-checkbox-on:after,\nhtml .ui-bar-a .ui-checkbox-on:after,\nhtml .ui-body-a .ui-checkbox-on:after,\nhtml body .ui-group-theme-a .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-a:after,\n/* Active flipswitch background */\n.ui-page-theme-a .ui-flipswitch-active,\nhtml .ui-bar-a .ui-flipswitch-active,\nhtml .ui-body-a .ui-flipswitch-active,\nhtml body .ui-group-theme-a .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-a .ui-slider-track .ui-btn-active,\nhtml .ui-bar-a .ui-slider-track .ui-btn-active,\nhtml .ui-body-a .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-a .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-a .ui-btn-active {\n\tbackground-color: \t\t#3388cc /*{a-active-background-color}*/;\n\tborder-color:\t \t\t#3388cc /*{a-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{a-active-color}*/;\n\ttext-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #005599 /*{a-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-a .ui-radio-on:after,\nhtml .ui-bar-a .ui-radio-on:after,\nhtml .ui-body-a .ui-radio-on:after,\nhtml body .ui-group-theme-a .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-a:after {\n\tborder-color:\t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-a .ui-btn:focus,\nhtml .ui-bar-a .ui-btn:focus,\nhtml .ui-body-a .ui-btn:focus,\nhtml body .ui-group-theme-a .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-a:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-a .ui-focus,\nhtml .ui-bar-a .ui-focus,\nhtml .ui-body-a .ui-focus,\nhtml body .ui-group-theme-a .ui-focus,\nhtml head + body .ui-btn-a.ui-focus,\nhtml head + body .ui-body-a.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#3388cc /*{a-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#3388cc /*{a-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* B\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-b,\n.ui-page-theme-b .ui-bar-inherit,\nhtml .ui-bar-b .ui-bar-inherit,\nhtml .ui-body-b .ui-bar-inherit,\nhtml body .ui-group-theme-b .ui-bar-inherit {\n\tbackground-color: \t\t\t#1d1d1d /*{b-bar-background-color}*/;\n\tborder-color:\t \t\t#1b1b1b /*{b-bar-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bar-color}*/;\n\ttext-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 0 /*{b-bar-shadow-radius}*/ \t#111 /*{b-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-b,\n.ui-page-theme-b,\n.ui-page-theme-b .ui-panel-wrapper {\n\tbackground-color: \t\t\t#252525 /*{b-page-background-color}*/;\n\tborder-color:\t \t\t#454545 /*{b-page-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-page-color}*/;\n\ttext-shadow: 0 /*{b-page-shadow-x}*/ 1px /*{b-page-shadow-y}*/ 0 /*{b-page-shadow-radius}*/ \t#111 /*{b-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-b,\n.ui-page-theme-b .ui-body-inherit,\nhtml .ui-bar-b .ui-body-inherit,\nhtml .ui-body-b .ui-body-inherit,\nhtml body .ui-group-theme-b .ui-body-inherit,\nhtml .ui-panel-page-container-b {\n\tbackground-color: \t\t\t#2a2a2a /*{b-body-background-color}*/;\n\tborder-color:\t \t\t#1d1d1d /*{b-body-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-body-color}*/;\n\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ \t#111 /*{b-body-shadow-color}*/;\n}\n.ui-body-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-b a,\nhtml .ui-bar-b a,\nhtml .ui-body-b a,\nhtml body .ui-group-theme-b a {\n\tcolor: #22aadd /*{b-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-b a:visited,\nhtml .ui-bar-b a:visited,\nhtml .ui-body-b a:visited,\nhtml body .ui-group-theme-b a:visited {\n    color: #22aadd /*{b-link-visited}*/;\n}\n.ui-page-theme-b a:hover,\nhtml .ui-bar-b a:hover,\nhtml .ui-body-b a:hover,\nhtml body .ui-group-theme-b a:hover {\n\tcolor: #0088bb /*{b-link-hover}*/;\n}\n.ui-page-theme-b a:active,\nhtml .ui-bar-b a:active,\nhtml .ui-body-b a:active,\nhtml body .ui-group-theme-b a:active {\n\tcolor: #0088bb /*{b-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-b .ui-btn,\nhtml .ui-bar-b .ui-btn,\nhtml .ui-body-b .ui-btn,\nhtml body .ui-group-theme-b .ui-btn,\nhtml head + body .ui-btn.ui-btn-b,\n/* Button visited */\n.ui-page-theme-b .ui-btn:visited,\nhtml .ui-bar-b .ui-btn:visited,\nhtml .ui-body-b .ui-btn:visited,\nhtml body .ui-group-theme-b .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-b:visited {\n\tbackground-color: \t\t\t#333 /*{b-bup-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bup-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n\ttext-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #111 /*{b-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-b .ui-btn:hover,\nhtml .ui-bar-b .ui-btn:hover,\nhtml .ui-body-b .ui-btn:hover,\nhtml body .ui-group-theme-b .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-b:hover {\n\tbackground-color: \t\t\t#373737 /*{b-bhover-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bhover-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n\ttext-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #111 /*{b-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-b .ui-btn:active,\nhtml .ui-bar-b .ui-btn:active,\nhtml .ui-body-b .ui-btn:active,\nhtml body .ui-group-theme-b .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-b:active {\n\tbackground-color: \t\t\t#404040 /*{b-bdown-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bdown-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n\ttext-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #111 /*{b-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-b .ui-btn.ui-btn-active,\nhtml .ui-bar-b .ui-btn.ui-btn-active,\nhtml .ui-body-b .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-b .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-b.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-b .ui-checkbox-on:after,\nhtml .ui-bar-b .ui-checkbox-on:after,\nhtml .ui-body-b .ui-checkbox-on:after,\nhtml body .ui-group-theme-b .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-b:after,\n/* Active flipswitch background */\n.ui-page-theme-b .ui-flipswitch-active,\nhtml .ui-bar-b .ui-flipswitch-active,\nhtml .ui-body-b .ui-flipswitch-active,\nhtml body .ui-group-theme-b .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-b .ui-slider-track .ui-btn-active,\nhtml .ui-bar-b .ui-slider-track .ui-btn-active,\nhtml .ui-body-b .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-b .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-b .ui-btn-active {\n\tbackground-color: \t\t#22aadd /*{b-active-background-color}*/;\n\tborder-color:\t \t\t#22aadd /*{b-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-active-color}*/;\n\ttext-shadow: 0 /*{b-active-shadow-x}*/ 1px /*{b-active-shadow-y}*/ 0 /*{b-active-shadow-radius}*/ #0088bb /*{b-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-b .ui-radio-on:after,\nhtml .ui-bar-b .ui-radio-on:after,\nhtml .ui-body-b .ui-radio-on:after,\nhtml body .ui-group-theme-b .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-b:after {\n\tborder-color:\t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-b .ui-btn:focus,\nhtml .ui-bar-b .ui-btn:focus,\nhtml .ui-body-b .ui-btn:focus,\nhtml body .ui-group-theme-b .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-b:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-b .ui-focus,\nhtml .ui-bar-b .ui-focus,\nhtml .ui-body-b .ui-focus,\nhtml body .ui-group-theme-b .ui-focus,\nhtml head + body .ui-btn-b.ui-focus,\nhtml head + body .ui-body-b.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#22aadd /*{b-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#22aadd /*{b-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Structure */\n/* Disabled\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-disabled deprecated in 1.4. :disabled not supported by IE8 so we use [disabled] */\n.ui-disabled,\n.ui-state-disabled,\nbutton[disabled],\n.ui-select .ui-btn.ui-state-disabled {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n\tcursor: default !important;\n\tpointer-events: none;\n}\n/* Focus state outline\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn:focus,\n.ui-btn.ui-focus {\n\toutline: 0;\n}\n/* Unset box-shadow in browsers that don't do it right */\n.ui-noboxshadow .ui-shadow,\n.ui-noboxshadow .ui-shadow-inset,\n.ui-noboxshadow .ui-overlay-shadow,\n.ui-noboxshadow .ui-shadow-icon.ui-btn:after,\n.ui-noboxshadow .ui-shadow-icon .ui-btn:after,\n.ui-noboxshadow .ui-focus,\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow  input:focus,\n.ui-noboxshadow .ui-panel {\n\t-webkit-box-shadow: none !important;\n\t-moz-box-shadow: none !important;\n\tbox-shadow: none !important;\n}\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow .ui-focus {\n\toutline-width: 1px;\n\toutline-style: auto;\n}\n/* Some unsets */\n.ui-mobile,\n.ui-mobile body {\n\theight: 99.9%;\n}\n.ui-mobile fieldset,\n.ui-page {\n\tpadding: 0;\n\tmargin: 0;\n}\n.ui-mobile a img,\n.ui-mobile fieldset {\n\tborder-width: 0;\n}\n/* Fixes for fieldset issues on IE10 and FF (see #6077) */\n.ui-mobile fieldset {\n\tmin-width: 0;\n}\n@-moz-document url-prefix() {\n\t.ui-mobile fieldset {\n\t\tdisplay: table-column;\n\t\tvertical-align: middle;\n\t}\n}\n/* Viewport */\n.ui-mobile-viewport {\n\tmargin: 0;\n\toverflow-x: visible;\n\t-webkit-text-size-adjust: 100%;\n\t-ms-text-size-adjust:none;\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n/* Issue #2066 */\nbody.ui-mobile-viewport,\ndiv.ui-mobile-viewport {\n\toverflow-x: hidden;\n}\n/* \"page\" containers - full-screen views, one should always be in view post-pageload */\n.ui-mobile [data-role=page],\n.ui-mobile [data-role=dialog],\n.ui-page {\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 100%;\n\tposition: absolute;\n\tdisplay: none;\n\tborder: 0;\n}\n/* On ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */\n.ui-page {\n\toutline: none;\n}\n.ui-mobile .ui-page-active {\n\tdisplay: block;\n\toverflow: visible;\n\toverflow-x: hidden;\n}\n@media screen and (orientation: portrait) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 420px;\n\t}\n}\n@media screen and (orientation: landscape) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 300px;\n\t}\n}\n/* Fouc */\n.ui-mobile-rendering > * {\n\tvisibility: hidden;\n}\n/* Non-js content hiding */\n.ui-nojs {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Loading screen */\n.ui-loading .ui-loader {\n\tdisplay: block;\n}\n.ui-loader {\n\tdisplay: none;\n\tz-index: 9999999;\n\tposition: fixed;\n\ttop: 50%;\n\tleft: 50%;\n\tborder:0;\n}\n.ui-loader-default {\n\tbackground: none;\n\tfilter: Alpha(Opacity=18);\n\topacity: .18;\n\twidth: 2.875em;\n\theight: 2.875em;\n\tmargin-left: -1.4375em;\n\tmargin-top: -1.4375em;\n}\n.ui-loader-verbose {\n\twidth: 12.5em;\n\tfilter: Alpha(Opacity=88);\n\topacity: .88;\n\tbox-shadow: 0 1px 1px -1px #fff;\n\theight: auto;\n\tmargin-left: -6.875em;\n\tmargin-top: -2.6875em;\n\tpadding: .625em;\n}\n.ui-loader-default h1 {\n\tfont-size: 0;\n\twidth: 0;\n\theight: 0;\n\toverflow: hidden;\n}\n.ui-loader-verbose h1 {\n\tfont-size: 1em;\n\tmargin: 0;\n\ttext-align: center;\n}\n.ui-loader .ui-icon-loading {\n\tbackground-color: #000;\n\tdisplay: block;\n\tmargin: 0;\n\twidth: 2.75em;\n\theight: 2.75em;\n\tpadding: .0625em;\n\t-webkit-border-radius: 2.25em;\n\tborder-radius: 2.25em;\n}\n.ui-loader-verbose .ui-icon-loading {\n\tmargin: 0 auto .625em;\n\tfilter: Alpha(Opacity=75);\n\topacity: .75;\n}\n.ui-loader-textonly {\n\tpadding: .9375em;\n\tmargin-left: -7.1875em;\n}\n.ui-loader-textonly .ui-icon-loading {\n\tdisplay: none;\n}\n.ui-loader-fakefix {\n\tposition: absolute;\n}\n/* Headers, content panels */\n.ui-bar,\n.ui-body {\n\tposition: relative;\n\tpadding: .4em 1em;\n\toverflow: hidden;\n\tdisplay: block;\n\tclear: both;\n}\n.ui-bar h1,\n.ui-bar h2,\n.ui-bar h3,\n.ui-bar h4,\n.ui-bar h5,\n.ui-bar h6 {\n\tmargin: 0;\n\tpadding: 0;\n\tfont-size: 1em;\n\tdisplay: inline-block;\n}\n.ui-header,\n.ui-footer {\n\tborder-width: 1px 0;\n\tborder-style: solid;\n\tposition: relative;\n}\n.ui-header:empty,\n.ui-footer:empty {\n\tmin-height: 2.6875em;\n}\n.ui-header .ui-title,\n.ui-footer .ui-title {\n\tfont-size: 1em;\n\tmin-height: 1.1em;\n\ttext-align: center;\n\tdisplay: block;\n\tmargin: 0 30%;\n\tpadding: .7em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\toutline: 0 !important;\n}\n.ui-footer .ui-title {\n\tmargin: 0 1em;\n}\n.ui-content {\n\tborder-width: 0;\n\toverflow: visible;\n\toverflow-x: hidden;\n\tpadding: 1em;\n}\n/* Corner styling for dialogs and popups */\n.ui-corner-all > .ui-header:first-child,\n.ui-corner-all > .ui-content:first-child,\n.ui-corner-all > .ui-footer:first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-corner-all > .ui-header:last-child,\n.ui-corner-all > .ui-content:last-child,\n.ui-corner-all > .ui-footer:last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n/* Buttons and icons */\n.ui-btn {\n\tfont-size: 16px;\n\tmargin: .5em 0;\n\tpadding: .7em 1em;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: center;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\tcursor: pointer;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n.ui-btn-icon-notext,\n.ui-header button.ui-btn.ui-btn-icon-notext,\n.ui-footer button.ui-btn.ui-btn-icon-notext {\n\tpadding: 0;\n\twidth: 1.75em;\n\theight: 1.75em;\n\ttext-indent: -9999px;\n\twhite-space: nowrap !important;\n}\n.ui-mini {\n\tfont-size: 12.5px;\n}\n.ui-mini .ui-btn {\n\tfont-size: inherit;\n}\n/* Make buttons in toolbars default to mini and inline. */\n.ui-header .ui-btn,\n.ui-footer .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-header .ui-controlgroup .ui-btn-icon-notext,\n.ui-footer .ui-controlgroup .ui-btn-icon-notext {\n    font-size: 12.5px;\n}\n/* To ensure same top and left/right position when ui-btn-left/right are added to something other than buttons. */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right {\n\tfont-size: 12.5px;\n}\n.ui-mini.ui-btn-icon-notext,\n.ui-mini .ui-btn-icon-notext,\n.ui-header .ui-btn-icon-notext,\n.ui-footer .ui-btn-icon-notext {\n\tfont-size: 16px;\t\n\tpadding: 0;\n}\n.ui-btn-inline {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin-right: .625em;\n}\n.ui-btn-icon-left {\n\tpadding-left: 2.5em;\n}\n.ui-btn-icon-right {\n\tpadding-right: 2.5em;\n}\n.ui-btn-icon-top {\n\tpadding-top: 2.5em;\n}\n.ui-btn-icon-bottom {\n\tpadding-bottom: 2.5em;\n}\n.ui-header .ui-btn-icon-top,\n.ui-footer .ui-btn-icon-top,\n.ui-header .ui-btn-icon-bottom,\n.ui-footer .ui-btn-icon-bottom {\n\tpadding-left: .3125em;\n\tpadding-right: .3125em;\n}\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tcontent: \"\";\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 22px;\n\theight: 22px;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after {\n\ttop: 50%;\n\tmargin-top: -11px;\n}\n.ui-btn-icon-left:after {\n\tleft: .5625em;\n}\n.ui-btn-icon-right:after {\n\tright: .5625em;\n}\n.ui-mini.ui-btn-icon-left:after,\n.ui-mini .ui-btn-icon-left:after,\n.ui-header .ui-btn-icon-left:after,\n.ui-footer .ui-btn-icon-left:after {\n\tleft: .37em;\n}\n.ui-mini.ui-btn-icon-right:after,\n.ui-mini .ui-btn-icon-right:after,\n.ui-header .ui-btn-icon-right:after,\n.ui-footer .ui-btn-icon-right:after {\n\tright: .37em;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after {\n\tleft: 50%;\n\tmargin-left: -11px;\n}\n.ui-btn-icon-top:after {\n\ttop: .5625em;\n}\n.ui-btn-icon-bottom:after {\n\ttop: auto;\n\tbottom: .5625em;\n}\n/* Buttons in header position classes */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right,\n.ui-btn-left > [class*=\"ui-\"],\n.ui-btn-right > [class*=\"ui-\"] {\n\tmargin: 0;\n}\n.ui-btn-left,\n.ui-btn-right {\n\tposition: absolute;\n\ttop: .24em;\n}\n.ui-btn-left {\n\tleft: .4em;\n}\n.ui-btn-right {\n\tright: .4em;\n}\n.ui-btn-icon-notext.ui-btn-left {\n\ttop: .3125em;\n\tleft: .3125em;\n}\n.ui-btn-icon-notext.ui-btn-right {\n\ttop: .3125em;\n\tright: .3125em;\n}\n/* Button elements */\nbutton.ui-btn,\n.ui-controlgroup-controls button.ui-btn-icon-notext {\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\twidth: 100%;\n}\nbutton.ui-btn-inline,\n.ui-header button.ui-btn,\n.ui-footer button.ui-btn {\n\twidth: auto;\n}\n/* Firefox adds a 1px border in a button element. We negate this to make sure they have the same height as other buttons in controlgroups. */\nbutton.ui-btn::-moz-focus-inner {\n\tborder: 0;\n}\nbutton.ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn {\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n\twidth: 1.75em;\n}\n/* Form labels */\n.ui-mobile label,\n.ui-controlgroup-label {\n\tdisplay: block;\n\tmargin: 0 0 .4em;\n}\n/* Accessible content hiding */\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-hide-label > label,\n.ui-hide-label .ui-controlgroup-label,\n.ui-hide-label .ui-rangeslider label,\n.ui-hidden-accessible {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Used for hiding elements by the filterable widget. You can also use this class to hide list items or buttons in controlgroups; this ensures correct corner styling. */\n.ui-screen-hidden {\n\tdisplay: none !important;\n}\n/* Transitions originally inspired by those from jQtouch, nice work, folks */\n.ui-mobile-viewport-transitioning,\n.ui-mobile-viewport-transitioning .ui-page {\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n.ui-page-pre-in {\n\topacity: 0;\n}\n.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.out {\n\t-webkit-animation-timing-function: ease-in;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-timing-function: ease-in;\n\t-moz-animation-duration: 225ms;\n\tanimation-timing-function: ease-in;\n\tanimation-duration: 225ms;\n}\n@-webkit-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-moz-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-webkit-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@-moz-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n.fade.out {\n\topacity: 0;\n\t-webkit-animation-duration: 125ms;\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-duration: 125ms;\n\t-moz-animation-name: fadeout;\n\tanimation-duration: 125ms;\n\tanimation-name: fadeout;\n}\n.fade.in {\n\topacity: 1;\n\t-webkit-animation-duration: 225ms;\n\t-webkit-animation-name: fadein;\n\t-moz-animation-duration: 225ms;\n\t-moz-animation-name: fadein;\n\tanimation-duration: 225ms;\n\tanimation-name: fadein;\n}\n.pop {\n\t-webkit-transform-origin: 50% 50%;\n\t-moz-transform-origin: 50% 50%;\n\ttransform-origin: 50% 50%;\n}\n.pop.in {\n\t-webkit-transform: scale(1);\n\t-webkit-animation-name: popin;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: scale(1);\n\t-moz-animation-name: popin;\n\t-moz-animation-duration: 350ms;\n\ttransform: scale(1);\n\tanimation-name: popin;\n\tanimation-duration: 350ms;\n    opacity: 1;\n}\n.pop.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n\topacity: 0;\n}\n.pop.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n\tanimation-name: fadein;\n}\n.pop.out.reverse {\n\t-webkit-transform: scale(.8);\n\t-webkit-animation-name: popout;\n\t-moz-transform: scale(.8);\n\t-moz-animation-name: popout;\n\ttransform: scale(.8);\n\tanimation-name: popout;\n}\n@-webkit-keyframes popin {\n    from {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n}\n@-moz-keyframes popin {\n    from {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n}\n@keyframes popin {\n    from {\n        transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        transform: scale(1);\n        opacity: 1;\n    }\n}\n@-webkit-keyframes popout {\n    from {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@-moz-keyframes popout {\n    from {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@keyframes popout {\n    from {\n        transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        transform: scale(.8);\n        opacity: 0;\n    }\n}\n/* keyframes for slidein from sides */\n@-webkit-keyframes slideinfromright {\n    from { -webkit-transform: translate3d(100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromright {\n    from { -moz-transform: translateX(100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromright {\n    from { transform: translateX(100%); }\n    to { transform: translateX(0); }\n}\n@-webkit-keyframes slideinfromleft {\n    from { -webkit-transform: translate3d(-100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromleft {\n    from { -moz-transform: translateX(-100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromleft {\n    from { transform: translateX(-100%); }\n    to { transform: translateX(0); }\n}\n/* keyframes for slideout to sides */\n@-webkit-keyframes slideouttoleft {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(-100%,0,0); }\n}\n@-moz-keyframes slideouttoleft {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(-100%); }\n}\n@keyframes slideouttoleft {\n    from { transform: translateX(0); }\n    to { transform: translateX(-100%); }\n}\n@-webkit-keyframes slideouttoright {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(100%,0,0); }\n}\n@-moz-keyframes slideouttoright {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(100%); }\n}\n@keyframes slideouttoright {\n    from { transform: translateX(0); }\n    to { transform: translateX(100%); }\n}\n.slide.out, .slide.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.slide.out {\n\t-webkit-transform: translate3d(-100%,0,0);\n\t-webkit-animation-name: slideouttoleft;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n}\n.slide.in {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromright;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromright;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromright;\n}\n.slide.out.reverse {\n\t-webkit-transform: translate3d(100%,0,0);\n\t-webkit-animation-name: slideouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n}\n.slide.in.reverse {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromleft;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromleft;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromleft;\n}\n.slidefade.out {\n\t-webkit-transform: translateX(-100%);\n\t-webkit-animation-name: slideouttoleft;\n\t-webkit-animation-duration: 225ms;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\t-moz-animation-duration: 225ms;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n\tanimation-duration: 225ms;\n}\n.slidefade.in {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n.slidefade.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: slideouttoright;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n\tanimation-duration: 200ms;\n}\n.slidefade.in.reverse {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n/* slide down */\n.slidedown.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slidedown.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfromtop;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfromtop;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfromtop;\n\tanimation-duration: 250ms;\n}\n.slidedown.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slidedown.out.reverse {\n\t-webkit-transform: translateY(-100%);\n\t-webkit-animation-name: slideouttotop;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(-100%);\n\t-moz-animation-name: slideouttotop;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(-100%);\n\tanimation-name: slideouttotop;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfromtop {\n    from { -webkit-transform: translateY(-100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfromtop {\n    from { -moz-transform: translateY(-100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfromtop {\n    from { transform: translateY(-100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttotop {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(-100%); }\n}\n@-moz-keyframes slideouttotop {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(-100%); }\n}\n@keyframes slideouttotop {\n    from { transform: translateY(0); }\n    to { transform: translateY(-100%); }\n}\n/* slide up */\n.slideup.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slideup.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfrombottom;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfrombottom;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfrombottom;\n\tanimation-duration: 250ms;\n}\n.slideup.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slideup.out.reverse {\n\t-webkit-transform: translateY(100%);\n\t-webkit-animation-name: slideouttobottom;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(100%);\n\t-moz-animation-name: slideouttobottom;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(100%);\n\tanimation-name: slideouttobottom;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfrombottom {\n    from { -webkit-transform: translateY(100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfrombottom {\n    from { -moz-transform: translateY(100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfrombottom {\n    from { transform: translateY(100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttobottom {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(100%); }\n}\n@-moz-keyframes slideouttobottom {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(100%); }\n}\n@keyframes slideouttobottom {\n    from { transform: translateY(0); }\n    to { transform: translateY(100%); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-flip {\n\t-webkit-perspective: 1000;\n\t-moz-perspective: 1000;\n\tperspective: 1000;\n\tposition: absolute;\n}\n.flip {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\tbackface-visibility: hidden;\n\ttransform: translateX(0);\n}\n.flip.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 175ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 175ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 175ms;\n}\n.flip.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 225ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 225ms;\n}\n.flip.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.flip.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-turn {\n\t-webkit-perspective: 200px;\n\t-moz-perspective: 200px;\n\t-ms-perspective: 200px;\n\tperspective: 200px;\n\tposition: absolute;\n}\n.turn {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-webkit-transform-origin: 0;\n\t\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\t-moz-transform-origin: 0;\n\t\n\tbackface-visibility :hidden;\n\ttransform: translateX(0);\n\ttransform-origin: 0;\n}\n.turn.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 125ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 125ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 125ms;\n}\n.turn.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 250ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 250ms;\n\t\n}\n.turn.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.turn.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* flow transition */\n.flow {\n\t-webkit-transform-origin: 50% 30%;\n\t-webkit-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\t-moz-transform-origin: 50% 30%;\t\n\t-moz-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\ttransform-origin: 50% 30%;\t\n\tbox-shadow: 0 0 20px rgba(0,0,0,.4);\n}\n.ui-dialog.flow {\n\t-webkit-transform-origin: none;\n\t-webkit-box-shadow: none;\n\t-moz-transform-origin: none;\t\n\t-moz-box-shadow: none;\n\ttransform-origin: none;\t\n\tbox-shadow: none;\n}\n.flow.out {\n\t-webkit-transform: translateX(-100%) scale(.7);\n\t-webkit-animation-name: flowouttoleft;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(-100%) scale(.7);\n\t-moz-animation-name: flowouttoleft;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(-100%) scale(.7);\n\tanimation-name: flowouttoleft;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.in {\n\t-webkit-transform: translateX(0) scale(1);\n\t-webkit-animation-name: flowinfromright;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(0) scale(1);\n\t-moz-animation-name: flowinfromright;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(0) scale(1);\n\tanimation-name: flowinfromright;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: flowouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: flowouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: flowouttoright;\n}\n.flow.in.reverse {\n\t-webkit-animation-name: flowinfromleft;\n\t-moz-animation-name: flowinfromleft;\n\tanimation-name: flowinfromleft;\n}\n@-webkit-keyframes flowouttoleft {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(-100%) scale(.7); }\n}\n@-moz-keyframes flowouttoleft {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(-100%) scale(.7); }\n}\n@keyframes flowouttoleft {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(-100%) scale(.7); }\n}\n@-webkit-keyframes flowouttoright {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform:  translateX(100%) scale(.7); }\n}\n@-moz-keyframes flowouttoright {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(100%) scale(.7); }\n}\n@keyframes flowouttoright {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(100%) scale(.7); }\n}\n@-webkit-keyframes flowinfromleft {\n    0% { -webkit-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromleft {\n    0% { -moz-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromleft {\n    0% { transform: translateX(-100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n@-webkit-keyframes flowinfromright {\n    0% { -webkit-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromright {\n    0% { -moz-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromright {\n    0% { transform: translateX(100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n.ui-field-contain,\n.ui-mobile fieldset.ui-field-contain {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n\tclear: both;\n\tpadding: .8em 0;\n}\n.ui-field-contain > label ~ [class*=\"ui-\"],\n.ui-field-contain .ui-controlgroup-controls {\n\tmargin: 0;\n}\n.ui-field-contain:last-child {\n\tborder-bottom-width: 0;\n}\n@media (min-width: 28em) {\n\t.ui-field-contain,\n\t.ui-mobile fieldset.ui-field-contain {\n\t\tpadding: 0;\n\t\tmargin: 1em 0;\n\t\tborder-bottom-width: 0;\n\t}\n\t.ui-field-contain:before,\n\t.ui-field-contain:after {\n\t\tcontent: \"\";\n\t\tdisplay: table;\n\t}\n\t.ui-field-contain:after {\n\t\tclear: both;\n\t}\n\t.ui-field-contain > label,\n\t.ui-field-contain .ui-controlgroup-label,\n\t.ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: left;\n\t\twidth: 20%;\n\t\tmargin: .5em 2% 0 0;\n\t}\n\t.ui-popup .ui-field-contain > label,\n\t.ui-popup .ui-field-contain .ui-controlgroup-label,\n\t.ui-popup .ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: none;\n\t\twidth: auto;\n\t\tmargin: 0 0 .4em;\n\t}\n\t.ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: left;\n\t\twidth: 78%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t}\n\t/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n\t.ui-hide-label > label ~ [class*=\"ui-\"],\n\t.ui-hide-label .ui-controlgroup-controls,\n\t.ui-popup .ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-popup .ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: none;\n\t\twidth: 100%;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline {\n\t\twidth: auto;\n\t\tmargin-right: .625em;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline.ui-btn-icon-notext {\n\t\twidth: 1.75em;\n\t}\n}\n/* content configurations. */\n.ui-grid-a,\n.ui-grid-b,\n.ui-grid-c,\n.ui-grid-d,\n.ui-grid-solo {\n\toverflow: hidden;\n}\n.ui-block-a,\n.ui-block-b,\n.ui-block-c,\n.ui-block-d,\n.ui-block-e {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfloat: left;\n\tmin-height: 1px;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n/* force new row */\n.ui-block-a {\n\tclear: left;\n}\nul.ui-grid-a,\nul.ui-grid-b,\nul.ui-grid-c,\nul.ui-grid-d,\nul.ui-grid-solo,\nli.ui-block-a,\nli.ui-block-b,\nli.ui-block-c,\nli.ui-block-d,\nli.ui-block-e {\n\tmargin-left: 0;\n\tmargin-right: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n/* No margin in grids for 100% width button elements until we can use max-width: fill-available; */\n[class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: 0;\n\tmargin-left: 0;\n}\n[class*=\"ui-block-\"] > .ui-btn,\n[class*=\"ui-block-\"] > .ui-select,\n[class*=\"ui-block-\"] > .ui-checkbox,\n[class*=\"ui-block-\"] > .ui-radio,\n[class*=\"ui-block-\"] > button.ui-btn-inline,\n[class*=\"ui-block-\"] > button.ui-btn-icon-notext,\n.ui-header [class*=\"ui-block-\"] > button.ui-btn,\n.ui-footer [class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: .3125em;\n\tmargin-left: .3125em;\n}\n.ui-grid-a > .ui-block-a,\n.ui-grid-a > .ui-block-b {\n\t/* width: 49.95%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 50%;\n}\n.ui-grid-b > .ui-block-a,\n.ui-grid-b > .ui-block-b,\n.ui-grid-b > .ui-block-c {\n\t/* width: 33.25%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 33.333%;\n}\n.ui-grid-c > .ui-block-a,\n.ui-grid-c > .ui-block-b,\n.ui-grid-c > .ui-block-c,\n.ui-grid-c > .ui-block-d {\n\t/* width: 24.925%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 25%;\n}\n.ui-grid-d > .ui-block-a,\n.ui-grid-d > .ui-block-b,\n.ui-grid-d > .ui-block-c,\n.ui-grid-d > .ui-block-d,\n.ui-grid-d > .ui-block-e {\n\t/* width: 19.925%; IE7 */\n\twidth: 20%;\n}\n.ui-grid-solo > .ui-block-a {\n\twidth: 100%;\n\tfloat: none; \n}\n/* preset breakpoint to switch to stacked grid styles below 35em (560px) */\n@media (max-width: 35em) {\n\t.ui-responsive > .ui-block-a,\n\t.ui-responsive > .ui-block-b,\n\t.ui-responsive > .ui-block-c,\n\t.ui-responsive > .ui-block-d,\n\t.ui-responsive > .ui-block-e {\n\t\twidth: 100%; \n\t\tfloat: none; \n\t}\n}\n/* fixed page header & footer configuration */\n.ui-header-fixed,\n.ui-footer-fixed {\n\tleft: 0;\n\tright: 0;\n\twidth: 100%;\n\tposition: fixed;\n\tz-index: 1000;\n}\n.ui-header-fixed {\n\ttop: -1px;\n\tpadding-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden {\n\ttop: 0;\n\tpadding-top: 0;\n}\n.ui-header-fixed .ui-btn-left,\n.ui-header-fixed .ui-btn-right {\n\tmargin-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden .ui-btn-left,\n.ui-header-fixed.ui-fixed-hidden .ui-btn-right {\n\tmargin-top: 0;\n}\n.ui-footer-fixed {\n\tbottom: -1px;\n\tpadding-bottom: 1px;\n}\n.ui-footer-fixed.ui-fixed-hidden {\n\tbottom: 0;\n\tpadding-bottom: 0;\n}\n.ui-header-fullscreen,\n.ui-footer-fullscreen {\n\tfilter: Alpha(Opacity=90);\n\topacity: .9;\n}\n/* updatePagePadding() will update the padding to actual height of header and footer. */\n.ui-page-header-fixed {\n\tpadding-top: 2.8125em;\n}\n.ui-page-footer-fixed {\n\tpadding-bottom: 2.8125em;\n}\n.ui-page-header-fullscreen > .ui-content,\n.ui-page-footer-fullscreen > .ui-content {\n\tpadding: 0;\n}\n.ui-fixed-hidden {\n\tposition: absolute;\n}\n/* Tap toggle: hide external fixed footer. See issue #6604 */\n.ui-footer-fixed.ui-fixed-hidden {\n  display: none;\n}\n.ui-page .ui-footer-fixed.ui-fixed-hidden {\n  display: block\n}\n.ui-page-header-fullscreen .ui-fixed-hidden,\n.ui-page-footer-fullscreen .ui-fixed-hidden {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-header-fixed .ui-btn,\n.ui-footer-fixed .ui-btn { \n\tz-index: 10;\n}\n/* workarounds for other widgets */\n.ui-android-2x-fixed .ui-li-has-thumb {\n\t-webkit-transform: translate3d(0,0,0);\n}\n.ui-navbar {\n\tmax-width: 100%;\n}\n.ui-navbar ul:before,\n.ui-navbar ul:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-navbar ul:after {\n\tclear: both;\n}\n.ui-navbar ul {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n\tdisplay: block;\n\tborder: 0;\n\tmax-width: 100%;\n\toverflow: visible;\n}\n.ui-navbar li .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: block;\n\tmargin: 0;\n\tborder-right-width: 0;\n}\n.ui-header .ui-navbar li button.ui-btn,\n.ui-footer .ui-navbar li button.ui-btn {\n\tmargin: 0;\n\twidth: 100%;\n}\n.ui-navbar .ui-btn:focus {\n\tz-index: 1;\n}\n/* fixes gaps caused by subpixel problem */\n.ui-navbar li:last-child .ui-btn {\n\tmargin-right: -4px;\n}\n.ui-navbar li:last-child .ui-btn:after {\n\tmargin-right: 4px;\n}\n.ui-content .ui-navbar li:last-child .ui-btn,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: 0;\n}\n.ui-content .ui-navbar li:last-child .ui-btn:after,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after {\n\tmargin-right: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after {\n\tmargin-right: 1px;\n}\n.ui-navbar .ui-grid-duo .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-header .ui-navbar .ui-btn,\n.ui-footer .ui-navbar .ui-btn {\n\tborder-top-width: 0;\n\tborder-bottom-width: 0;\n}\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-header .ui-title ~ .ui-navbar .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n/* Hide the native input element */\n.ui-input-btn input {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tbackground: #fff;\n\tbackground: rgba(255,255,255,0);\n\tfilter: Alpha(Opacity=0);\n\topacity: .1;\n\tfont-size: 1px;\n\ttext-indent: -9999px;\n\tz-index: 2;\n}\n/* Fixes IE/WP filter alpha opacity bugs */\n.ui-input-btn.ui-state-disabled input {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible {\n\tmargin: 0 -1em;\n}\n.ui-collapsible-inset,\n.ui-collapsible-set {\n\tmargin: .5em 0;\n}\n.ui-collapsible-heading {\n\tdisplay: block;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n}\n.ui-collapsible-heading .ui-btn {\n\ttext-align: left;\n\tmargin: 0;\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n}\n.ui-collapsible-heading .ui-btn-icon-top,\n.ui-collapsible-heading .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-collapsible-inset .ui-collapsible-heading .ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-collapsible-collapsed + .ui-collapsible:not(.ui-collapsible-inset) > .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-collapsible-heading-status {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible-content {\n\tdisplay: block;\n\tmargin: 0;\t\n\tpadding: .5em 1em;\n}\n.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n\tborder-top-width: 0;\n\tborder-bottom-width: 1px;\n\tborder-style: solid;\n}\n.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 1px;\n\tborder-right-width: 1px;\n}\n.ui-collapsible-inset .ui-collapsible-content {\n\tmargin: 0;\n}\n.ui-collapsible-content-collapsed {\n\tdisplay: none;\n}\n.ui-collapsible-set > .ui-collapsible.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-collapsible-heading,\n.ui-collapsible-heading > .ui-btn {\n\t-webkit-border-radius: inherit;\t\n\tborder-radius: inherit;\t\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\t\n\tborder-top-left-radius: inherit;\t\t\n}\n.ui-collapsible-content,\n.ui-collapsible-set .ui-collapsible.ui-last-child {\n\t-webkit-border-bottom-right-radius: inherit;\t\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\t\n\tborder-bottom-left-radius: inherit;\t\t\n}\n.ui-collapsible-themed-content:not(.ui-collapsible-collapsed) > .ui-collapsible-heading {\n\t-webkit-border-bottom-right-radius: 0;\t\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\t\n\tborder-bottom-left-radius: 0;\t\t\n}\n.ui-collapsible-set .ui-collapsible {\n\tmargin: -1px -1em 0;\n}\n.ui-collapsible-set .ui-collapsible-inset {\n\tmargin: -1px 0 0;\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\tmargin-top: 0;\n}\n.ui-controlgroup,\nfieldset.ui-controlgroup {\n\tpadding: 0;\n\tmargin: .5em 0;\n}\n.ui-field-contain .ui-controlgroup,\n.ui-field-contain fieldset.ui-controlgroup {\n\tmargin: 0;\n}\n.ui-mini .ui-controlgroup-label {\n\tfont-size: 16px;\n}\n.ui-controlgroup.ui-mini .ui-btn-icon-notext,\n.ui-controlgroup .ui-mini.ui-btn-icon-notext {\n\tfont-size: inherit;\n}\n.ui-controlgroup-controls .ui-btn,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-select {\n\tmargin: 0;\n}\n.ui-controlgroup-controls .ui-btn:focus,\n.ui-controlgroup-controls .ui-btn.ui-focus {\n\tz-index: 1;\n}\n.ui-controlgroup-controls li {\n\tlist-style: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:before,\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tclear: both;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls li > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select {\n\tfloat: left;\n\tclear: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,\n.ui-controlgroup-controls .ui-btn-icon-notext {\n\twidth: auto;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext {\n\twidth: 1.5em;\n}\n .ui-controlgroup-controls .ui-btn-icon-notext {\n\theight: auto;\n\tpadding: .7em 1em;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-bottom-width: 1px;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn {\n\tborder-right-width: 0;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-right-width: 1px;\n}\n.ui-controlgroup-controls .ui-btn-corner-all,\n.ui-controlgroup-controls .ui-btn.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-controlgroup-controls,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-select,\n.ui-controlgroup-controls li {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-last-child {\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-controls a.ui-shadow:not(:focus),\n.ui-controlgroup-controls button.ui-shadow:not(:focus),\n.ui-controlgroup-controls div.ui-shadow:not(.ui-focus) {\n\t-moz-box-shadow: none;\n\t-webkit-box-shadow: none;\n\tbox-shadow: none;\n}\n/* Fixes legend not wrapping on IE10 */\n.ui-controlgroup-label legend {\n\tmax-width: 100%;\n}\n.ui-controlgroup-controls > label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-dialog {\n\t background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */\n}\n.ui-dialog-contain {\n\twidth: 92.5%;\n\tmax-width: 500px;\n\tmargin: 10% auto 1em auto;\n\tpadding: 0;\n\tposition: relative;\n\ttop: -1em;\n}\n.ui-dialog-contain > .ui-header, \n.ui-dialog-contain > .ui-content, \n.ui-dialog-contain > .ui-footer { \n\tdisplay: block;\n\tposition: relative; \n\twidth: auto;\n\tmargin: 0;\n}\n.ui-dialog-contain > .ui-header {\n\toverflow: hidden;\n\tz-index: 10; \n\tpadding: 0;\n\tborder-top-width: 0;\n}\n.ui-dialog-contain > .ui-footer {\n\tz-index: 10; \n\tpadding: 0 1em; \n\tborder-bottom-width: 0;\n}\n.ui-popup-open .ui-header-fixed,\n.ui-popup-open .ui-footer-fixed {\n\tposition: absolute !important; /* See issues #4816, #4844 and #4874 and popup.js */\n}\n.ui-popup-screen {\n\tbackground-image: url(\"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\"); /* Necessary to set some form of background to ensure element is clickable in IE6/7. While legacy IE won't understand the data-URI'd image, it ensures no additional requests occur in all other browsers with little overhead. */\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 1px;\n\tposition: absolute;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 1099;\n}\n.ui-popup-screen.in {\n\topacity: 0.5;\n\tfilter: Alpha(Opacity=50);\n}\n.ui-popup-screen.out {\n\topacity: 0;\n\tfilter: Alpha(Opacity=0);\n}\n.ui-popup-container {\n\tz-index: 1100;\n\tdisplay: inline-block;\n\tposition: absolute;\n\tpadding: 0;\n\toutline: 0;\n}\n.ui-popup {\n\tposition: relative;\n}\n.ui-popup.ui-body-inherit {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-hidden {\n\tleft: 0;\n\ttop: 0;\n\tposition: absolute !important;\n\tvisibility: hidden;\n}\n.ui-popup-truncate {\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-popup.ui-content,\n.ui-popup .ui-content {\n\toverflow: visible;\n}\n.ui-popup > .ui-header {\n\tborder-top-width: 0;\n}\n.ui-popup > .ui-footer {\n\tborder-bottom-width: 0;\n}\n.ui-popup > p,\n.ui-popup > h1,\n.ui-popup > h2,\n.ui-popup > h3,\n.ui-popup > h4,\n.ui-popup > h5,\n.ui-popup > h6 {\n\tmargin: .5em .4375em;\n}\n.ui-popup > span {\n\tdisplay: block;\n\tmargin: .5em .4375em;\n}\n.ui-popup-container .ui-content > p,\n.ui-popup-container .ui-content > h1,\n.ui-popup-container .ui-content > h2,\n.ui-popup-container .ui-content > h3,\n.ui-popup-container .ui-content > h4,\n.ui-popup-container .ui-content > h5,\n.ui-popup-container .ui-content > h6 {\n\tmargin: .5em 0;\n}\n.ui-popup-container .ui-content > span {\n\tmargin: 0;\n}\n.ui-popup-container .ui-content > p:first-child,\n.ui-popup-container .ui-content > h1:first-child,\n.ui-popup-container .ui-content > h2:first-child,\n.ui-popup-container .ui-content > h3:first-child,\n.ui-popup-container .ui-content > h4:first-child,\n.ui-popup-container .ui-content > h5:first-child,\n.ui-popup-container .ui-content > h6:first-child {\n\tmargin-top: 0;\n}\n.ui-popup-container .ui-content > p:last-child,\n.ui-popup-container .ui-content > h1:last-child,\n.ui-popup-container .ui-content > h2:last-child,\n.ui-popup-container .ui-content > h3:last-child,\n.ui-popup-container .ui-content > h4:last-child,\n.ui-popup-container .ui-content > h5:last-child,\n.ui-popup-container .ui-content > h6:last-child {\n\tmargin-bottom: 0;\n}\n.ui-popup > img {\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tvertical-align: middle;\n}\n.ui-popup:not(.ui-content) > img:only-child,\n.ui-popup:not(.ui-content) > .ui-btn-left:first-child + img:last-child,\n.ui-popup:not(.ui-content) > .ui-btn-right:first-child + img:last-child {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-popup iframe {\n\tvertical-align: middle;\n}\n.ui-popup > .ui-btn-left,\n.ui-popup > .ui-btn-right {\n\tposition: absolute; \n\ttop: -11px;\n\tmargin: 0;\n\tz-index: 1101;\n}\n.ui-popup > .ui-btn-left {\n\tleft: -11px;\n}\n.ui-popup > .ui-btn-right {\n\tright: -11px;\n}\n/* Dimensions related to the popup arrow\n-----------------------------------------------------------------------------------------------------------*/\n/* desired triangle height: 10px */\n/**\n * guide for the arrow - its width, height, and offset are theme-dependent and\n * should be expessed as left, right, top, bottom, so that the element bearing\n * such a class becomes stretched inside its parent position: relative element.\n * The left/top/right/bottom specified below should reflect the corresponding\n * border radii and so it leaves room for the shadow:\n *     ..--------------------..\n *   .\"        ^ top           \".\n *  /          v                 \\\n * |     +------------------+     |\n * |     |                  |     |\n * | left|                  |right|\n * |<--->|                  |<--->|\n * |     +------------------+     |\n *  \\          ^                 /\n *   `.        v bottom        .'\n *     \"\"--------------------\"\"\n * The idea is that the top/left of the arrow container box does not move to a\n * coordinate smaller than the top/left of the guide and the right/bottom of\n * the arrow container box does not move to a coordinate larger than the\n * bottom/right of the guide. This will help us avoid the following situation:\n *        ..--------------------..\n *      .\"        ^ top           \".\n *   /|/          v                 \\\n *  / |     +------------------+     |\n *  \\ |     |                  |     |\n *   \\| left|                  |right|\n *    |<--->|                  |<--->|\n *    |     +------------------+     |\n *     \\          ^                 /\n *      `.        v bottom        .'\n *        \"\"--------------------\"\"\n * The arrow should not receive a top/left coordinate such that it is too close\n * to one of the corners, because then at first the shadow of the arrow and,\n * given a coordinate even closer to the corner, even the body of the arrow will\n * \"stick out\" of the corner of the popup. The guide provides a hint to the\n * arrow positioning code as to which range of values is acceptable for the\n * arrow container's top/left coordinate.\n **/\n.ui-popup-arrow-container {\n\twidth: 20px;\n\theight: 20px;\n}\n/* aside from the \"infinities\" (-1000,2000), triangle height is used */\n.ui-popup-arrow-container.ui-popup-arrow-l {\n\tleft: -10px;\n\tclip: rect(-1000px,10px,2000px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-t {\n\ttop: -10px;\n\tclip: rect(-1000px,2000px,10px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-r {\n\tright: -10px;\n\tclip: rect(-1000px,2000px,2000px,10px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-b {\n\tbottom: -10px;\n\tclip: rect(10px,2000px,1000px,-1000px);\n}\n/**\n * For each side, the arrow is twice the desired size and its corner is aligned\n * with the edge of the container:\n *                                           \n *           /\\         /\\                +----+       /\\\n *          /  \\       /  \\               | /\\ |top   /  \\\n *      +----+  \\     /  +----+       +-->|/  \\|     /    \\\n *  left| /  |   \\   /   |  \\ |right  |   |    |    /      \\\n *      |/   |    \\ /    |   \\|       |  /|    |\\  /        \\\n *      |\\   |    / \\    |   /|       | / +----+ \\ \\ +----+ /\n *      | \\  |   /   \\   |  / |       | \\        /  \\|    |/\n *      +----+  /     \\  +----+       |  \\      /    |    |\n *       ^  \\  /       \\  /  ^        |   \\    /  +->|\\  /|\n *       |   \\/         \\/   |        |    \\  /   |  | \\/ |bottom\n *       |                   |        |     \\/    |  +----+\n *       +-------------------+--------+-----------+\n *                           |\n *                    arrow container\n *                     (clips arrow)\n **/\n.ui-popup-arrow-container .ui-popup-arrow {\n\t/* (4*desired triangle height)/sqrt(2) - does not account for border - centred within the outer rectangle */\n\twidth: 28.284271247px;\n\theight: 28.284271247px;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: 5.857864376px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: -14.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow {\n\tleft: 5.857864376px;\n\ttop: -4.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow {\n\tleft: -14.142135623px;\n\ttop: -4.142135623px;\n}\n/* Fix rotation center for oldIE - see http://www.useragentman.com/IETransformsTranslator/ */\n.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -7.0710678118654755px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -4.142135623730951px;\n}\n \n.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow {\n    margin-left: -7.0710678118654755px;\n    margin-top: -5.857864376269049px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow {\n    margin-left: -4.142135623730951px;\n    margin-top: -5.857864376269049px;\n}\n/* structure */\n.ui-popup > .ui-popup-arrow-guide {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tvisibility: hidden;\n}\n.ui-popup-arrow-container {\n\tposition: absolute;\n}\n.ui-popup-arrow {\n\t-webkit-transform: rotate(45deg);\n\t-moz-transform: rotate(45deg);\n\t-ms-transform: rotate(45deg);\n\ttransform: rotate(45deg);\n\tposition: absolute;\n\toverflow: hidden;\n\tbox-sizing: border-box;\n}\n.ui-popup-arrow-container.ie .ui-popup-arrow {\n\t-ms-filter: \"progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod='auto expand')\";\n\tfilter: progid:DXImageTransform.Microsoft.Matrix(\n\t      \tM11=0.7071067811865474,\n        \tM12=-0.7071067811865477,\n        \tM21=0.7071067811865477,\n        \tM22=0.7071067811865474,\n        \tSizingMethod='auto expand');\n}\n.ui-checkbox,\n.ui-radio {\n\tmargin: .5em 0;\n\tposition: relative;\n}\n.ui-checkbox .ui-btn,\n.ui-radio .ui-btn {\n\tmargin: 0;\n\ttext-align: left;\n\twhite-space: normal; /* Nowrap + ellipsis doesn't work on label. Issue #1419. */\n\tz-index: 2;\n}\n.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,\n.ui-controlgroup .ui-radio .ui-btn.ui-focus {\n\tz-index: 3;\n}\n.ui-checkbox .ui-btn-icon-top,\n.ui-radio .ui-btn-icon-top,\n.ui-checkbox .ui-btn-icon-bottom,\n.ui-radio .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,\n.ui-controlgroup-horizontal .ui-radio .ui-btn:after {\n\tcontent: none;\n\tdisplay: none;\n}\n/* Native input positioning */\n.ui-checkbox input,\n.ui-radio input {\n\tposition: absolute;\n\tleft: .466em;\n\ttop: 50%;\n\twidth: 22px;\n\theight: 22px;\n\tmargin: -11px 0 0 0;\n\toutline: 0 !important;\n\tz-index: 1;\n}\n.ui-controlgroup-horizontal .ui-checkbox input,\n.ui-controlgroup-horizontal .ui-radio input {\n\tleft: 50%;\n\tmargin-left: -9px;\n}\n.ui-checkbox input:disabled,\n.ui-radio input:disabled {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select {\n\tmargin-top: .5em;\n\tmargin-bottom: .5em; /* no shorthand for margin because it would override margin-right for inline selects */\n\tposition: relative;\n}\n.ui-select > select {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select .ui-btn {\n\tmargin: 0;\n\topacity: 1; /* Fixes #2588: When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select (including \"inherit\") without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */\n}\n.ui-select .ui-btn select {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 1.5em;\n\tmin-height: 100%;\n\theight: 3em;\n\tmax-height: 100%;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 2;\n}\n@-moz-document url-prefix() {\n\t.ui-select .ui-btn select {\n\t\topacity: 0.0001;\n\t}\n}\n/* Display none because of issues with IE/WP's filter alpha opacity */\n.ui-select .ui-state-disabled select {\n\tdisplay: none;\n}\n/* Because we add all classes of the select and option elements to the span... */ \n.ui-select span.ui-state-disabled {\n\tfilter: Alpha(Opacity=100);\n\topacity: 1;\n}\n.ui-select .ui-btn.ui-select-nativeonly {\n\tborder-radius: 0;\n\tborder: 0;\n}\n.ui-select .ui-btn.ui-select-nativeonly select {\n\topacity: 1;\n\ttext-indent: 0;\n\tdisplay: block;\n}\n/* ui-li-count is styled in the listview CSS. We set padding and offset here because select supports icon position while listview doesn't. */\n.ui-select .ui-li-has-count.ui-btn {\n\tpadding-right: 2.8125em;\n}\n.ui-select .ui-li-has-count.ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-select .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n/* We set the rules for the span as well to fix an issue on Chrome with text-overflow ellipsis for the button in combination with text-align center. */\n.ui-select .ui-btn > span:not(.ui-li-count) {\n\tdisplay: block;\n\ttext-overflow: ellipsis;\n\toverflow: hidden !important;\n\twhite-space: nowrap;\n}\n.ui-selectmenu.ui-popup {\n\tmin-width: 11em;\n}\n.ui-selectmenu .ui-dialog-contain {\n\toverflow: hidden;\n}\n.ui-selectmenu .ui-header {\n\tmargin: 0;\n\tpadding: 0;\n\tborder-width: 0;\n}\n.ui-selectmenu.ui-dialog .ui-header {\n\tz-index: 1;\n\tposition: relative;\n}\n.ui-selectmenu.ui-popup .ui-header {\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n}\n/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button.  this shim's content in there */\n.ui-selectmenu.ui-popup .ui-header h1:after {\n\tcontent: '.';\n\tvisibility: hidden;\n}\n.ui-selectmenu .ui-header .ui-title {\n\tmargin: 0 2.875em;\n}\n.ui-selectmenu.ui-dialog .ui-content {\n\toverflow: visible;\n\tz-index: 1;\n}\n.ui-selectmenu .ui-selectmenu-list {\n\tmargin: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-header:not(.ui-screen-hidden) + .ui-selectmenu-list {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-top-left-radius: 0;\n\tborder-top-left-radius: 0;\n}\n.ui-header.ui-screen-hidden + .ui-selectmenu-list li.ui-first-child .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-selectmenu .ui-btn.ui-li-divider {\n\tcursor: default;\n}\n.ui-selectmenu .ui-selectmenu-placeholder {\n\tdisplay: none;\n}\n.ui-listview,\n.ui-listview > li {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n.ui-content .ui-listview,\n.ui-panel-inner > .ui-listview {\n\tmargin: -1em;\n}\n.ui-content .ui-listview-inset,\n.ui-panel-inner > .ui-listview-inset {\n\tmargin: 1em 0;\n}\n.ui-collapsible-content > .ui-listview {\n\tmargin: -.5em -1em;\n}\n.ui-collapsible-content > .ui-listview-inset {\n\tmargin: .5em 0;\n}\n.ui-listview > li {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tmargin: 0;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: left;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li > .ui-btn:focus {\n\tz-index: 1;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tborder-width: 1px 0 0 0;\n\tborder-style: solid;\n}\n.ui-listview-inset > .ui-li-static,\n.ui-listview-inset > .ui-li-divider,\n.ui-listview-inset > li > a.ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-listview > .ui-li-static.ui-last-child,\n.ui-listview > .ui-li-divider.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 1px;\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child,\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-listview > li.ui-first-child,\n.ui-listview > li.ui-first-child > a.ui-btn {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n}\n.ui-listview > li.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-listview > li.ui-li-has-alt > a.ui-btn {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n.ui-listview > li.ui-first-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-top-left-radius: 0;\t\n\tborder-top-left-radius: 0;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-listview > li.ui-last-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-listview > li.ui-first-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\t\n}\n.ui-listview > li.ui-last-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\t\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-listview > .ui-li-static {\n\tpadding: .7em 1em;\n}\n.ui-listview > .ui-li-divider {\n\tpadding: .5em 1.143em;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tcursor: default;\n\toutline: 0; /* Dividers in custom selectmenus have tabindex */\n}\n.ui-listview > .ui-li-has-count > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-count,\n.ui-listview > .ui-li-divider.ui-li-has-count {\n\tpadding-right: 2.8125em;\n}\n.ui-listview > .ui-li-has-count > .ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-listview > .ui-li-has-thumb > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-thumb {\n\tmin-height: 3.625em;\n\tpadding-left: 6.25em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-icon {\n\tmin-height: 1.25em;\n\tpadding-left: 2.5em;\n}\n/* Used by both listview and custom multiple select button */\n.ui-li-count {\n\tposition: absolute;\n\tfont-size: 12.5px;\n\tfont-weight: bold;\n\ttext-align: center;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tpadding: 0 .48em;\n\tline-height: 1.6em;\n\tmin-height: 1.6em;\n\tmin-width: .64em;\n\tright: .8em;\n\ttop: 50%;\n\tmargin-top: -.88em;\n}\n.ui-listview .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n.ui-listview .ui-li-has-thumb > img:first-child,\n.ui-listview .ui-li-has-thumb > .ui-btn > img:first-child,\n.ui-listview .ui-li-has-thumb .ui-li-thumb {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\tmax-height: 5em;\n\tmax-width: 5em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > img:first-child,\n.ui-listview > .ui-li-has-icon > .ui-btn > img:first-child {\n\tposition: absolute;\n\tleft: .625em;\n\ttop: .9em;\n\tmax-height: 1em;\n\tmax-width: 1em;\n}\n.ui-listview > li h1,\n.ui-listview > li h2,\n.ui-listview > li h3,\n.ui-listview > li h4,\n.ui-listview > li h5,\n.ui-listview > li h6 {\n\tfont-size: 1em;\n\tfont-weight: bold;\n\tdisplay: block;\n\tmargin: .45em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li p {\n\tfont-size: .75em;\n\tfont-weight: normal;\n\tdisplay: block;\n\tmargin: .6em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview .ui-li-aside {\n\tposition: absolute;\n\ttop: 1em;\n\tright: 3.333em;\n\tmargin: 0;\n\ttext-align: right;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn {\n\tmargin-right: 2.5em;\n\tborder-right-width: 0;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tposition: absolute;\n\twidth: 2.5em;\n\theight: 100%;\n\tmin-height: auto;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-left-width: 1px;\n\ttop: 0;\n\tright: 0;\n\tmargin: 0;\n\tpadding: 0;\n\tz-index: 2;\n}\n.ui-listview-inset > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tborder-right-width: 1px;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn:focus {\n\tz-index: 3;\n}\nol.ui-listview,\nol.ui-listview > .ui-li-divider {\n\tcounter-reset: listnumbering;\n}\nol.ui-listview > li > .ui-btn,\nol.ui-listview > li.ui-li-static {\n\tvertical-align: middle;\n}\nol.ui-listview > li > .ui-btn:first-child:before,\nol.ui-listview > li.ui-li-static:before,\nol.ui-listview > li.ui-field-contain > label:before,\nol.ui-listview > li.ui-field-contain > .ui-controlgroup-label:before {\n\tdisplay: inline-block;\n\tfont-size: .9em;\n\tfont-weight: normal;\n\tpadding-right: .3em;\n\tmin-width: 1.4em;\n\tline-height: 1.5;\n\tvertical-align: middle;\n\tcounter-increment: listnumbering;\n\tcontent: counter(listnumbering) \".\";\n}\nol.ui-listview > li.ui-field-contain:before {\n\tcontent: none;\n\tdisplay: none;\n}\nol.ui-listview > li h1:first-child,\nol.ui-listview > li h2:first-child,\nol.ui-listview > li h3:first-child,\nol.ui-listview > li h4:first-child,\nol.ui-listview > li h5:first-child,\nol.ui-listview > li h6:first-child,\nol.ui-listview > li p:first-child,\nol.ui-listview > li img:first-child + * {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\nol.ui-listview > li h1:first-child ~ *,\nol.ui-listview > li h2:first-child ~ *,\nol.ui-listview > li h3:first-child ~ *,\nol.ui-listview > li h4:first-child ~ *,\nol.ui-listview > li h5:first-child ~ *,\nol.ui-listview > li h6:first-child ~ *,\nol.ui-listview > li p:first-child ~ *,\nol.ui-listview > li img:first-child + * ~ * {\n\tmargin-top: 0;\n\ttext-indent: 2.04em; /* (1.4em + .3em) * .9em / .75em */\n}\nhtml .ui-filterable + .ui-listview,\nhtml .ui-filterable.ui-listview {\n\tmargin-top: .5em;\n}\n.ui-collapsible-content > form.ui-filterable {\n\tmargin-top: -.5em;\n}\n.ui-collapsible-content > .ui-input-search.ui-filterable {\n\tmargin-top: 0;\n}\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 1px;\n}\ndiv.ui-slider {\n\theight: 30px;\n\tmargin: .5em 0;\n\tpadding: 0;\n\t-ms-touch-action: pan-y pinch-zoom double-tap-zoom;\n}\ndiv.ui-slider:before,\ndiv.ui-slider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\ndiv.ui-slider:after {\n\tclear: both;\n}\ninput.ui-slider-input {\n\tdisplay: block;\n\tfloat: left;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tmargin: 0;\n\tpadding: 4px;\n\twidth: 40px;\n\theight: 20px;\n\tline-height: 20px;\n\tborder-width: 1px;\n\tborder-style: solid;\n\toutline: 0;\n\ttext-align: center;\n\tvertical-align: text-bottom;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tappearance: none;\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-slider-input::-webkit-outer-spin-button,\n.ui-slider-input::-webkit-inner-spin-button {\n\t-webkit-appearance: none;\n\tmargin: 0;\n}\n.ui-slider-track {\n\tposition: relative;\n\toverflow: visible;\n\tborder-width: 1px;\n\tborder-style: solid;\n\theight: 15px;\n\tmargin: 0 15px 0 68px;\n\ttop: 6px;\n}\n.ui-slider-track.ui-mini {\n\theight: 12px;\n\ttop: 8px;\n}\n.ui-slider-track .ui-slider-bg {\n\theight: 100%;\n}\n/* High level of specificity to override button margins in grids */\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tposition: absolute;\n\tz-index: 1;\n\ttop: 50%;\n\twidth: 28px;\n\theight: 28px;\n\tmargin: -15px 0 0 -15px;\n\toutline: 0;\n\tpadding: 0;\n}\n.ui-slider-track.ui-mini .ui-slider-handle {\n\theight: 14px;\n\twidth: 14px;\n\tmargin: -8px 0 0 -8px;\n}\nselect.ui-slider-switch {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\ndiv.ui-slider-switch {\n\tdisplay: inline-block;\n\theight: 32px;\n\twidth: 5.8em;\n\ttop: 0;\n}\n/* reset the clearfix */\ndiv.ui-slider-switch:before,\ndiv.ui-slider-switch:after {\n\tdisplay: none;\n\tclear: none;\n}\ndiv.ui-slider-switch.ui-mini {\n\theight: 29px;\n\ttop: 0;\n}\n.ui-slider-inneroffset {\n\tmargin: 0 16px;\n\tposition: relative;\n\tz-index: 1;\n}\n.ui-slider-switch.ui-mini .ui-slider-inneroffset {\n\tmargin: 0 15px 0 14px;\n}\n.ui-slider-switch .ui-btn.ui-slider-handle {\n\tmargin: 1px 0 0 -15px;\n}\n.ui-slider-switch.ui-mini .ui-slider-handle {\n\twidth: 25px;\n\theight: 25px;\n\tmargin: 1px 0 0 -13px;\n\tpadding: 0;\n}\n.ui-slider-handle-snapping {\n\t-webkit-transition: left 70ms linear;\n\t-moz-transition: left 70ms linear;\n\ttransition: left 70ms linear;\n}\n.ui-slider-switch .ui-slider-label {\n\tposition: absolute;\n\ttext-align: center;\n\twidth: 100%;\n\toverflow: hidden;\n\tfont-size: 16px;\n\ttop: 0;\n\tline-height: 2;\n\tmin-height: 100%;\n\twhite-space: nowrap;\n\tcursor: pointer;\n}\n.ui-slider-switch.ui-mini .ui-slider-label {\n\tfont-size: 14px;\n}\n.ui-slider-switch .ui-slider-label-a {\n\tz-index: 1;\n\tleft: 0;\n\ttext-indent: -1.5em;\n}\n.ui-slider-switch .ui-slider-label-b {\n\tz-index: 0;\n\tright: 0;\n\ttext-indent: 1.5em;\n}\n/* The corner radii for ui-slider-switch/track can be specified in theme CSS. The bg and handle inherits. */\n.ui-slider-track .ui-slider-bg,\n.ui-slider-switch .ui-slider-label,\n.ui-slider-switch .ui-slider-inneroffset,\n.ui-slider-handle {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-field-contain div.ui-slider-switch {\n\tmargin: 0;\n}\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-field-contain div.ui-slider-switch,\n.ui-field-contain.ui-hide-label div.ui-slider-switch,\nhtml .ui-popup .ui-field-contain div.ui-slider-switch {\n\tdisplay: inline-block;\n\twidth: 5.8em;\n}\n/* slider tooltip\n-----------------------------------------------------------------------------------------------------------*/\n.ui-slider-popup {\n\twidth: 64px;\n\theight: 64px;\n\tfont-size: 36px;\n\tpadding-top: 14px;\n\topacity: 0.8;\n}\n.ui-slider-popup {\n\tposition: absolute !important;\n\ttext-align: center;\n\tz-index: 100;\n}\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tfont-size: .9em;\n\tline-height: 30px;\n}\n.ui-rangeslider {\n\tmargin: .5em 0;\n}\n.ui-rangeslider:before,\n.ui-rangeslider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-rangeslider:after {\n\tclear: both;\n}\n.ui-rangeslider .ui-slider-input.ui-rangeslider-last {\n\tfloat: right;\n}\n.ui-rangeslider .ui-rangeslider-sliders {\n\tposition: relative;\n\toverflow: visible;\n\theight: 30px;\n\tmargin: 0 68px;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track {\n\tposition: absolute;\n\ttop: 6px;\n\tright: 0;\n\tleft: 0;\n\tmargin: 0;\n}\n.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track {\n\ttop: 8px;\n}\n.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg {\n\tdisplay: none;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\tbackground-color: transparent;\n\tbackground: none;\n\tborder-width: 0;\n\theight: 0;\n}\n/* this makes ie6 and ie7 set height to 0 to fix z-index problem */\nhtml >/**/body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 15px;\n\tborder-width: 1px;\n}\nhtml >/**/body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 12px;\n}\n/* Hide the second label (the first is moved outside the div) */\ndiv.ui-rangeslider label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-field-contain .ui-rangeslider input.ui-slider-input,\n.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,\n.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,\n.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders {\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n}\n.ui-input-text,\n.ui-input-search {\n\tmargin: .5em 0;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-mini {\n\tmargin: .446em;\n}\n.ui-input-text input,\n.ui-input-search input,\ntextarea.ui-input-text {\n\tpadding: .4em;\n\tline-height: 1.4em;\n\tdisplay: block;\n\twidth: 100%;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\toutline: 0;\n}\n.ui-input-text input,\n.ui-input-search input {\n\tmargin: 0;\n\tmin-height: 2.2em;\n\ttext-align: left; /* Opera aligns type=\"date\" right by default */\n\tborder: 0;\n\tbackground: transparent none;\n\t-webkit-appearance: none;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\ntextarea.ui-input-text {\n\toverflow: auto;\n\tresize: vertical;\n}\n.ui-mini .ui-input-text input,\n.ui-mini .ui-input-search input,\n.ui-input-text.ui-mini input,\n.ui-input-search.ui-mini input,\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tfont-size: 14px;\n}\n/* Same margin for mini textareas as other mini sized widgets (12.5/14 * 0.5em) */\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tmargin: .446em 0;\n}\n.ui-input-has-clear,\n.ui-input-search {\n\tposition: relative;\n}\n/* Padding on the div instead of input because of browser spinners etc. */\n.ui-input-has-clear {\n\tpadding-right: 2.375em;\n}\n.ui-mini.ui-input-has-clear {\n\tpadding-right: 2.923em;\n}\n.ui-input-has-clear input {\n\tpadding-right: 0;\n\t/* Autofill on Chrome has bg color so we unset corners right as well. */\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n/* Search icon */\n.ui-input-search input {\n\tpadding-left: 1.75em;\n}\n.ui-input-search:after {\n\tposition: absolute;\n\tleft: .3125em;\n\ttop: 50%;\n\tmargin-top: -7px;\n\tcontent: \"\";\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\twidth: 14px;\n\theight: 14px;\n\tfilter: Alpha(Opacity=50);\n\topacity: .5;\n}\n.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,\n.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear {\n\tposition: absolute;\n\tright: 0;\n\ttop: 50%;\n\tmargin: -14px .3125em 0;\n\tborder: 0;\n\tbackground-color: transparent;\n}\n.ui-input-search .ui-input-clear-hidden,\n.ui-input-text .ui-input-clear-hidden {\n\tdisplay: none;\n}\n/* Resolves issue #5166: Added to support issue introduced in Firefox 15. We can likely remove this in the future. */\n.ui-input-text input::-moz-placeholder,\n.ui-input-search input::-moz-placeholder,\ntextarea.ui-input-text::-moz-placeholder {\n\tcolor: #aaa;\n}\n/* Same for IE10 */\n.ui-input-text input:-ms-input-placeholder,\n.ui-input-search input:-ms-input-placeholder,\ntextarea.ui-input-text:-ms-input-placeholder {\n\tcolor: #aaa;\n}\n/* Resolves issue #5131: Width of textinput depends on its type,\nfor Android 4.1 */\n.ui-input-text input[type=number]::-webkit-outer-spin-button {\n\tmargin: 0;\n}\n/* Resolves issue #5756: Textinput in IE10 has a default clear button */\n.ui-input-text input::-ms-clear,\n.ui-input-search input::-ms-clear {\n\tdisplay: none;\n}\n.ui-input-text input:focus,\n.ui-input-search input:focus {\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n\tbox-shadow: none;\n}\ntextarea.ui-input-text.ui-textinput-autogrow {\n\toverflow: hidden;\n}\n.ui-textinput-autogrow-resize {\n\t-webkit-transition: height 0.25s;\n\t-o-transition: height 0.25s;\n\t-moz-transition: height 0.25s;\n\ttransition: height 0.25s;\n}\n.ui-flipswitch {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\twidth: 5.875em; /* Override this and padding-left in next rule if you use labels other than \"on/off\" and need more space */\n\theight: 1.875em;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tmargin: .5em 0;\n\toverflow: hidden;\n\t-webkit-transition-property: padding, width, background-color, color, border-color;\n\t-moz-transition-property: padding, width, background-color, color, border-color;\n\t-o-transition-property: padding, width, background-color, color, border-color;\n\ttransition-property: padding, width, background-color, color, border-color;\n\t-webkit-transition-duration: 100ms;\n\t-moz-transition-duration: 100ms;\n\t-o-transition-duration: 100ms;\n\ttransition-duration: 100ms;\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\tcursor: pointer;\n}\n.ui-flipswitch.ui-flipswitch-active {\n\tpadding-left: 4em;  /* Override this and width in previous rule if you use labels other than \"on/off\" and need more space */\n\twidth: 1.875em;\n}\n.ui-flipswitch-input {\n\tposition: absolute;\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n\tborder: 0;\n\toutline: 0;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on,\n.ui-flipswitch .ui-flipswitch-off {\n\tfloat: left;\n\theight: 1.75em;\n\tmargin: .0625em;\n\tline-height: 1.65em;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on {\n\twidth: 1.75em;\n\tpadding: 0;\n\ttext-indent: -2.6em; /* Override this to center text if you use a label other than \"on\" */\n\ttext-align: left;\n\tborder-width: 1px;\n\tborder-style: solid;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-radius: inherit;\n\toverflow: visible;\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n.ui-flipswitch .ui-flipswitch-off {\n\tpadding: 1px;\n\ttext-indent: 1em; /* Override this to center text if you use a label other than \"off\" */\n}\n/* Override field container CSS to prevent the flipswitch from becomming full width */\nhtml .ui-field-contain > label + .ui-flipswitch,\nhtml .ui-popup .ui-field-contain > label + .ui-flipswitch {\n\tdisplay: inline-block;\n\twidth: 5.875em; /* If you override the width for .ui-flipswitch you should repeat the same value here */\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-field-contain .ui-flipswitch.ui-flipswitch-active,\n.ui-popup .ui-field-contain .ui-flipswitch.ui-flipswitch-active {\n\twidth: 1.875em;\n}\n.ui-table {\n\tborder: 0;\n\tborder-collapse: collapse;\n\tpadding: 0;\n\twidth: 100%;\n}\n.ui-table th,\n.ui-table td {\n\tline-height: 1.5em;\n\ttext-align: left;\n\tpadding: .4em .5em;\n\tvertical-align:top;\n}\n.ui-table th .ui-btn,\n.ui-table td .ui-btn {\n\tline-height: normal;\n}\n.ui-table th {\n\tfont-weight: bold;\n}\n.ui-table caption {\n\ttext-align: left;\n\tmargin-bottom: 1.4em;\n\topacity: .5;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-columntoggle-btn {\n\tfloat: right;\n\tmargin-bottom: .8em;\n}\n/* Remove top/bottom margins around the fieldcontain on check list */\n.ui-table-columntoggle-popup fieldset {\n\tmargin:0;\n}\n.ui-table-columntoggle {\n\tclear: both;\n}\n/* Hide all prioritized columns by default */\n@media only all {\n\tth.ui-table-priority-6,\n\ttd.ui-table-priority-6,\n\tth.ui-table-priority-5,\n\ttd.ui-table-priority-5,\n\tth.ui-table-priority-4,\n\ttd.ui-table-priority-4,\n\tth.ui-table-priority-3,\n\ttd.ui-table-priority-3,\n\tth.ui-table-priority-2,\n\ttd.ui-table-priority-2,\n\tth.ui-table-priority-1,\n\ttd.ui-table-priority-1 {\n\t\tdisplay: none;\n\t}\n}\n/* Preset breakpoints if \".ui-responsive\" class added to table */\n/* Show priority 1 at 320px (20em x 16px) */\n@media screen and (min-width: 20em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-1 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 2 at 480px (30em x 16px) */\n@media screen and (min-width: 30em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-2 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 3 at 640px (40em x 16px) */\n@media screen and (min-width: 40em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-3 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 4 at 800px (50em x 16px) */\n@media screen and (min-width: 50em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-4 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 5 at 960px (60em x 16px) */\n@media screen and (min-width: 60em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-5 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 6 at 1,120px (70em x 16px) */\n@media screen and (min-width: 70em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-6 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Unchecked manually: Always hide */\n.ui-table-columntoggle th.ui-table-cell-hidden,\n.ui-table-columntoggle td.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden {\n\tdisplay: none;\n}\n/* Checked manually: Always show */\n.ui-table-columntoggle th.ui-table-cell-visible,\n.ui-table-columntoggle td.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible {\n\tdisplay: table-cell;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-reflow td .ui-table-cell-label,\n.ui-table-reflow th .ui-table-cell-label { \n\tdisplay: none;\n}\n/* Mobile first styles: Begin with the stacked presentation at narrow widths */ \n@media only all {\n\t/* Hide the table headers */ \n\t.ui-table-reflow thead td, \n\t.ui-table-reflow thead th {\n\t\tdisplay: none;\n\t}\n\t/* Show the table cells as a block level element */ \n\t.ui-table-reflow td,\n\t.ui-table-reflow th { \n\t\ttext-align: left;\n\t\tdisplay: block;\n\t}\n\t/* Add a fair amount of top margin to visually separate each row when stacked */  \n\t.ui-table-reflow tbody th {\n\t\tmargin-top: 3em;\n\t}\n\t/* Make the label elements a percentage width */ \n\t.ui-table-reflow td .ui-table-cell-label,\n\t.ui-table-reflow th .ui-table-cell-label { \n\t\tpadding: .4em; \n\t\tmin-width: 30%; \n\t\tdisplay: inline-block;\n\t\tmargin: -.4em 1em -.4em -.4em;\n\t}\n\t/* For grouped headers, have a different style to visually separate the levels by classing the first label in each col group */ \n\t.ui-table-reflow th .ui-table-cell-label-top,\n\t.ui-table-reflow td .ui-table-cell-label-top {\n\t\tdisplay: block;\n\t\tpadding: .4em 0;\n\t\tmargin: .4em 0;\n\t\ttext-transform: uppercase;\n\t\tfont-size: .9em;\n\t\tfont-weight: normal;\n\t}\n}\n/* Breakpoint to show as a standard table at 560px (35em x 16px) or wider */ \n@media ( min-width: 35em ) {\n\t/* Show the table header rows */ \n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th,\n\t.ui-table-reflow.ui-responsive tbody th,\n\t.ui-table-reflow.ui-responsive tbody td,\n\t.ui-table-reflow.ui-responsive thead td,\n\t.ui-table-reflow.ui-responsive thead th {\n\t\tdisplay: table-cell;\n\t\tmargin: 0;\n\t}\n\t/* Hide the labels in each cell */ \n\t.ui-table-reflow.ui-responsive td .ui-table-cell-label,\n\t.ui-table-reflow.ui-responsive th .ui-table-cell-label { \n\t\tdisplay: none;\n\t}\n}\n/* Hack to make IE9 and WP7.5 treat cells like block level elements, scoped to ui-responsive class */ \n/* Applied in a max-width media query up to the table layout breakpoint so we don't need to negate this*/ \n@media ( max-width: 35em ) {\n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th {\n\t\twidth: 100%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t\tfloat: left;\n\t\tclear: left;\n\t}\n}\n/* Panel */\n.ui-panel {\n\twidth: 17em;\n\tmin-height: 100%;\n\tmax-height: none;\n\tborder-width: 0;\n\tposition: absolute;\n\ttop: 0;\n\tdisplay: block;\n}\n.ui-panel-closed {\n\twidth: 0;\n\tmax-height: 100%;\n\toverflow: hidden;\n\tvisibility: hidden;\n\tleft: 0;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-panel-fixed {\n\tposition: fixed;\n\tbottom: -1px; /* Fixes gap on Chrome for Android */\n\tpadding-bottom: 1px;\n}\n.ui-panel-display-reveal {\n\tz-index: 1;\n}\n.ui-panel-display-push {\n\tz-index: 999;\n}\n.ui-panel-display-overlay {\n\tz-index: 1001; /* Fixed toolbars have z-index 1000 */\n}\n.ui-panel-inner {\n\tpadding: 1em;\n}\n/* Container, page and wrapper */\n.ui-panel-page-container {\n\toverflow-x: visible;\n}\n.ui-panel-page-container-themed .ui-page-active {\n\tbackground: none;\n}\n.ui-panel-wrapper {\n\tposition: relative;\n\tmin-height: inherit;\n\tborder: 0;\n\toverflow-x: hidden;\n\tz-index: 999;\n}\n/* Fixed toolbars */\n.ui-panel-fixed-toolbar {\n\toverflow-x: hidden;\n}\n/* Dismiss */\n.ui-panel-dismiss {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\theight: 100%;\n\tz-index: 1002;\n\tdisplay: none;\n}\n.ui-panel-dismiss-open {\n\tdisplay: block;\n}\n/* Animate class is added to panel, wrapper and fixed toolbars */\n.ui-panel-animate {\n\t-webkit-transition: -webkit-transform 300ms ease;\n\t-webkit-transition-duration: 300ms;\n\t-moz-transition: -moz-transform 300ms ease;\n\ttransition: transform 300ms ease;\n}\n/* Fix for Windows Phone issue #6349: unset the transition for transforms in case of fixed toolbars. */\n@media screen and ( max-device-width: 768px ) {\n\t.ui-page-header-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-page-footer-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: none;\n\t}\n\t/* We need a transitionend event ... */\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: -ms-transform 1ms;\n\t\t-ms-transform: rotate(0deg);\n\t}\n}\n/* Hardware acceleration for smoother transitions on WebKit browsers */\n.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal) {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translate3d(0,0,0);\n}\n/* Panel positioning (for overlay and push) */\n/* Panel left closed */\n.ui-panel-position-left {\n\tleft: -17em;\n}\n/* Panel left closed animated */\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-push {\n\tleft: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Panel left open */\n.ui-panel-position-left.ui-panel-display-reveal, /* Unset \"panel left closed\" for reveal */\n.ui-panel-open.ui-panel-position-left {\n\tleft: 0;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Panel right closed */\n.ui-panel-position-right {\n\tright: -17em;\n}\n/* Panel right closed animated */\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-push {\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-position-right.ui-panel-display-reveal, /* Unset \"panel right closed\" for reveal */\n.ui-panel-position-right.ui-panel-open {\n\tright: 0;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Wrapper and fixed toolbars positioning (for reveal and push) */\n/* Panel left open */\n.ui-panel-page-content-position-left {\n\tleft: 17em;\n\tright: -17em;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-page-content-position-left {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-page-content-position-right {\n\tleft: -17em;\n\tright: 17em;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-page-content-position-right {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Dismiss model open */\n.ui-panel-dismiss-open.ui-panel-dismiss-position-left {\n\tleft: 17em;\n}\n.ui-panel-dismiss-open.ui-panel-dismiss-position-right {\n\tright: 17em;\n}\n/* Shadows and borders */\n.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-display-overlay {\n\t-webkit-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-overlay {\n\t-webkit-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-panel-page-content-position-left.ui-panel-page-content-display-push {\n\tmargin-left: 1px;\n\twidth: auto;\n}\n.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\tborder-left-width: 1px;\n\tmargin-left: -1px;\n}\n.ui-panel-page-content-position-right.ui-panel-page-content-display-push {\n\tmargin-right: 1px;\n\twidth: auto;\n}\n/* Responsive: wrap on wide viewports once open */\n@media (min-width:55em) {\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left {\n\t\tmargin-right: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right {\n\t\tmargin-left: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open {\n\t\twidth: auto;\t\n\t}\n\t.ui-responsive-panel .ui-panel-dismiss-display-push,\n\t.ui-responsive-panel.ui-page-active ~ .ui-panel-dismiss-display-push {\n\t\tdisplay: none;\n\t}\n}\n.ui-tabs {\n\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n\tpadding: .2em;\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile.structure-1.4.5.css",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n/* Some unsets */\n.ui-mobile,\n.ui-mobile body {\n\theight: 99.9%;\n}\n.ui-mobile fieldset,\n.ui-page {\n\tpadding: 0;\n\tmargin: 0;\n}\n.ui-mobile a img,\n.ui-mobile fieldset {\n\tborder-width: 0;\n}\n/* Fixes for fieldset issues on IE10 and FF (see #6077) */\n.ui-mobile fieldset {\n\tmin-width: 0;\n}\n@-moz-document url-prefix() {\n\t.ui-mobile fieldset {\n\t\tdisplay: table-column;\n\t\tvertical-align: middle;\n\t}\n}\n/* Viewport */\n.ui-mobile-viewport {\n\tmargin: 0;\n\toverflow-x: visible;\n\t-webkit-text-size-adjust: 100%;\n\t-ms-text-size-adjust:none;\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n/* Issue #2066 */\nbody.ui-mobile-viewport,\ndiv.ui-mobile-viewport {\n\toverflow-x: hidden;\n}\n/* \"page\" containers - full-screen views, one should always be in view post-pageload */\n.ui-mobile [data-role=page],\n.ui-mobile [data-role=dialog],\n.ui-page {\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 100%;\n\tposition: absolute;\n\tdisplay: none;\n\tborder: 0;\n}\n/* On ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */\n.ui-page {\n\toutline: none;\n}\n.ui-mobile .ui-page-active {\n\tdisplay: block;\n\toverflow: visible;\n\toverflow-x: hidden;\n}\n@media screen and (orientation: portrait) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 420px;\n\t}\n}\n@media screen and (orientation: landscape) {\n\t.ui-mobile .ui-page {\n\t\tmin-height: 300px;\n\t}\n}\n/* Fouc */\n.ui-mobile-rendering > * {\n\tvisibility: hidden;\n}\n/* Non-js content hiding */\n.ui-nojs {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Loading screen */\n.ui-loading .ui-loader {\n\tdisplay: block;\n}\n.ui-loader {\n\tdisplay: none;\n\tz-index: 9999999;\n\tposition: fixed;\n\ttop: 50%;\n\tleft: 50%;\n\tborder:0;\n}\n.ui-loader-default {\n\tbackground: none;\n\tfilter: Alpha(Opacity=18);\n\topacity: .18;\n\twidth: 2.875em;\n\theight: 2.875em;\n\tmargin-left: -1.4375em;\n\tmargin-top: -1.4375em;\n}\n.ui-loader-verbose {\n\twidth: 12.5em;\n\tfilter: Alpha(Opacity=88);\n\topacity: .88;\n\tbox-shadow: 0 1px 1px -1px #fff;\n\theight: auto;\n\tmargin-left: -6.875em;\n\tmargin-top: -2.6875em;\n\tpadding: .625em;\n}\n.ui-loader-default h1 {\n\tfont-size: 0;\n\twidth: 0;\n\theight: 0;\n\toverflow: hidden;\n}\n.ui-loader-verbose h1 {\n\tfont-size: 1em;\n\tmargin: 0;\n\ttext-align: center;\n}\n.ui-loader .ui-icon-loading {\n\tbackground-color: #000;\n\tdisplay: block;\n\tmargin: 0;\n\twidth: 2.75em;\n\theight: 2.75em;\n\tpadding: .0625em;\n\t-webkit-border-radius: 2.25em;\n\tborder-radius: 2.25em;\n}\n.ui-loader-verbose .ui-icon-loading {\n\tmargin: 0 auto .625em;\n\tfilter: Alpha(Opacity=75);\n\topacity: .75;\n}\n.ui-loader-textonly {\n\tpadding: .9375em;\n\tmargin-left: -7.1875em;\n}\n.ui-loader-textonly .ui-icon-loading {\n\tdisplay: none;\n}\n.ui-loader-fakefix {\n\tposition: absolute;\n}\n/* Headers, content panels */\n.ui-bar,\n.ui-body {\n\tposition: relative;\n\tpadding: .4em 1em;\n\toverflow: hidden;\n\tdisplay: block;\n\tclear: both;\n}\n.ui-bar h1,\n.ui-bar h2,\n.ui-bar h3,\n.ui-bar h4,\n.ui-bar h5,\n.ui-bar h6 {\n\tmargin: 0;\n\tpadding: 0;\n\tfont-size: 1em;\n\tdisplay: inline-block;\n}\n.ui-header,\n.ui-footer {\n\tborder-width: 1px 0;\n\tborder-style: solid;\n\tposition: relative;\n}\n.ui-header:empty,\n.ui-footer:empty {\n\tmin-height: 2.6875em;\n}\n.ui-header .ui-title,\n.ui-footer .ui-title {\n\tfont-size: 1em;\n\tmin-height: 1.1em;\n\ttext-align: center;\n\tdisplay: block;\n\tmargin: 0 30%;\n\tpadding: .7em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\toutline: 0 !important;\n}\n.ui-footer .ui-title {\n\tmargin: 0 1em;\n}\n.ui-content {\n\tborder-width: 0;\n\toverflow: visible;\n\toverflow-x: hidden;\n\tpadding: 1em;\n}\n/* Corner styling for dialogs and popups */\n.ui-corner-all > .ui-header:first-child,\n.ui-corner-all > .ui-content:first-child,\n.ui-corner-all > .ui-footer:first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-corner-all > .ui-header:last-child,\n.ui-corner-all > .ui-content:last-child,\n.ui-corner-all > .ui-footer:last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n/* Buttons and icons */\n.ui-btn {\n\tfont-size: 16px;\n\tmargin: .5em 0;\n\tpadding: .7em 1em;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: center;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n\tcursor: pointer;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n.ui-btn-icon-notext,\n.ui-header button.ui-btn.ui-btn-icon-notext,\n.ui-footer button.ui-btn.ui-btn-icon-notext {\n\tpadding: 0;\n\twidth: 1.75em;\n\theight: 1.75em;\n\ttext-indent: -9999px;\n\twhite-space: nowrap !important;\n}\n.ui-mini {\n\tfont-size: 12.5px;\n}\n.ui-mini .ui-btn {\n\tfont-size: inherit;\n}\n/* Make buttons in toolbars default to mini and inline. */\n.ui-header .ui-btn,\n.ui-footer .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-header .ui-controlgroup .ui-btn-icon-notext,\n.ui-footer .ui-controlgroup .ui-btn-icon-notext {\n    font-size: 12.5px;\n}\n/* To ensure same top and left/right position when ui-btn-left/right are added to something other than buttons. */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right {\n\tfont-size: 12.5px;\n}\n.ui-mini.ui-btn-icon-notext,\n.ui-mini .ui-btn-icon-notext,\n.ui-header .ui-btn-icon-notext,\n.ui-footer .ui-btn-icon-notext {\n\tfont-size: 16px;\t\n\tpadding: 0;\n}\n.ui-btn-inline {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin-right: .625em;\n}\n.ui-btn-icon-left {\n\tpadding-left: 2.5em;\n}\n.ui-btn-icon-right {\n\tpadding-right: 2.5em;\n}\n.ui-btn-icon-top {\n\tpadding-top: 2.5em;\n}\n.ui-btn-icon-bottom {\n\tpadding-bottom: 2.5em;\n}\n.ui-header .ui-btn-icon-top,\n.ui-footer .ui-btn-icon-top,\n.ui-header .ui-btn-icon-bottom,\n.ui-footer .ui-btn-icon-bottom {\n\tpadding-left: .3125em;\n\tpadding-right: .3125em;\n}\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tcontent: \"\";\n\tposition: absolute;\n\tdisplay: block;\n\twidth: 22px;\n\theight: 22px;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after {\n\ttop: 50%;\n\tmargin-top: -11px;\n}\n.ui-btn-icon-left:after {\n\tleft: .5625em;\n}\n.ui-btn-icon-right:after {\n\tright: .5625em;\n}\n.ui-mini.ui-btn-icon-left:after,\n.ui-mini .ui-btn-icon-left:after,\n.ui-header .ui-btn-icon-left:after,\n.ui-footer .ui-btn-icon-left:after {\n\tleft: .37em;\n}\n.ui-mini.ui-btn-icon-right:after,\n.ui-mini .ui-btn-icon-right:after,\n.ui-header .ui-btn-icon-right:after,\n.ui-footer .ui-btn-icon-right:after {\n\tright: .37em;\n}\n.ui-btn-icon-notext:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after {\n\tleft: 50%;\n\tmargin-left: -11px;\n}\n.ui-btn-icon-top:after {\n\ttop: .5625em;\n}\n.ui-btn-icon-bottom:after {\n\ttop: auto;\n\tbottom: .5625em;\n}\n/* Buttons in header position classes */\n.ui-header .ui-btn-left,\n.ui-header .ui-btn-right,\n.ui-btn-left > [class*=\"ui-\"],\n.ui-btn-right > [class*=\"ui-\"] {\n\tmargin: 0;\n}\n.ui-btn-left,\n.ui-btn-right {\n\tposition: absolute;\n\ttop: .24em;\n}\n.ui-btn-left {\n\tleft: .4em;\n}\n.ui-btn-right {\n\tright: .4em;\n}\n.ui-btn-icon-notext.ui-btn-left {\n\ttop: .3125em;\n\tleft: .3125em;\n}\n.ui-btn-icon-notext.ui-btn-right {\n\ttop: .3125em;\n\tright: .3125em;\n}\n/* Button elements */\nbutton.ui-btn,\n.ui-controlgroup-controls button.ui-btn-icon-notext {\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\twidth: 100%;\n}\nbutton.ui-btn-inline,\n.ui-header button.ui-btn,\n.ui-footer button.ui-btn {\n\twidth: auto;\n}\n/* Firefox adds a 1px border in a button element. We negate this to make sure they have the same height as other buttons in controlgroups. */\nbutton.ui-btn::-moz-focus-inner {\n\tborder: 0;\n}\nbutton.ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn {\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n\twidth: 1.75em;\n}\n/* Form labels */\n.ui-mobile label,\n.ui-controlgroup-label {\n\tdisplay: block;\n\tmargin: 0 0 .4em;\n}\n/* Accessible content hiding */\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-hide-label > label,\n.ui-hide-label .ui-controlgroup-label,\n.ui-hide-label .ui-rangeslider label,\n.ui-hidden-accessible {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n/* Used for hiding elements by the filterable widget. You can also use this class to hide list items or buttons in controlgroups; this ensures correct corner styling. */\n.ui-screen-hidden {\n\tdisplay: none !important;\n}\n/* Transitions originally inspired by those from jQtouch, nice work, folks */\n.ui-mobile-viewport-transitioning,\n.ui-mobile-viewport-transitioning .ui-page {\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n.ui-page-pre-in {\n\topacity: 0;\n}\n.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.out {\n\t-webkit-animation-timing-function: ease-in;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-timing-function: ease-in;\n\t-moz-animation-duration: 225ms;\n\tanimation-timing-function: ease-in;\n\tanimation-duration: 225ms;\n}\n@-webkit-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-moz-keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@keyframes fadein {\n    from { opacity: 0; }\n    to { opacity: 1; }\n}\n@-webkit-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@-moz-keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n@keyframes fadeout {\n    from { opacity: 1; }\n    to { opacity: 0; }\n}\n.fade.out {\n\topacity: 0;\n\t-webkit-animation-duration: 125ms;\n\t-webkit-animation-name: fadeout;\n\t-moz-animation-duration: 125ms;\n\t-moz-animation-name: fadeout;\n\tanimation-duration: 125ms;\n\tanimation-name: fadeout;\n}\n.fade.in {\n\topacity: 1;\n\t-webkit-animation-duration: 225ms;\n\t-webkit-animation-name: fadein;\n\t-moz-animation-duration: 225ms;\n\t-moz-animation-name: fadein;\n\tanimation-duration: 225ms;\n\tanimation-name: fadein;\n}\n.pop {\n\t-webkit-transform-origin: 50% 50%;\n\t-moz-transform-origin: 50% 50%;\n\ttransform-origin: 50% 50%;\n}\n.pop.in {\n\t-webkit-transform: scale(1);\n\t-webkit-animation-name: popin;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: scale(1);\n\t-moz-animation-name: popin;\n\t-moz-animation-duration: 350ms;\n\ttransform: scale(1);\n\tanimation-name: popin;\n\tanimation-duration: 350ms;\n    opacity: 1;\n}\n.pop.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n\topacity: 0;\n}\n.pop.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-moz-animation-name: fadein;\n\tanimation-name: fadein;\n}\n.pop.out.reverse {\n\t-webkit-transform: scale(.8);\n\t-webkit-animation-name: popout;\n\t-moz-transform: scale(.8);\n\t-moz-animation-name: popout;\n\ttransform: scale(.8);\n\tanimation-name: popout;\n}\n@-webkit-keyframes popin {\n    from {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n}\n@-moz-keyframes popin {\n    from {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n}\n@keyframes popin {\n    from {\n        transform: scale(.8);\n        opacity: 0;\n    }\n    to {\n        transform: scale(1);\n        opacity: 1;\n    }\n}\n@-webkit-keyframes popout {\n    from {\n        -webkit-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -webkit-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@-moz-keyframes popout {\n    from {\n        -moz-transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        -moz-transform: scale(.8);\n        opacity: 0;\n    }\n}\n@keyframes popout {\n    from {\n        transform: scale(1);\n        opacity: 1;\n    }\n    to {\n        transform: scale(.8);\n        opacity: 0;\n    }\n}\n/* keyframes for slidein from sides */\n@-webkit-keyframes slideinfromright {\n    from { -webkit-transform: translate3d(100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromright {\n    from { -moz-transform: translateX(100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromright {\n    from { transform: translateX(100%); }\n    to { transform: translateX(0); }\n}\n@-webkit-keyframes slideinfromleft {\n    from { -webkit-transform: translate3d(-100%,0,0); }\n    to { -webkit-transform: translate3d(0,0,0); }\n}\n@-moz-keyframes slideinfromleft {\n    from { -moz-transform: translateX(-100%); }\n    to { -moz-transform: translateX(0); }\n}\n@keyframes slideinfromleft {\n    from { transform: translateX(-100%); }\n    to { transform: translateX(0); }\n}\n/* keyframes for slideout to sides */\n@-webkit-keyframes slideouttoleft {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(-100%,0,0); }\n}\n@-moz-keyframes slideouttoleft {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(-100%); }\n}\n@keyframes slideouttoleft {\n    from { transform: translateX(0); }\n    to { transform: translateX(-100%); }\n}\n@-webkit-keyframes slideouttoright {\n    from { -webkit-transform: translate3d(0,0,0); }\n    to { -webkit-transform: translate3d(100%,0,0); }\n}\n@-moz-keyframes slideouttoright {\n    from { -moz-transform: translateX(0); }\n    to { -moz-transform: translateX(100%); }\n}\n@keyframes slideouttoright {\n    from { transform: translateX(0); }\n    to { transform: translateX(100%); }\n}\n.slide.out, .slide.in {\n\t-webkit-animation-timing-function: ease-out;\n\t-webkit-animation-duration: 350ms;\n\t-moz-animation-timing-function: ease-out;\n\t-moz-animation-duration: 350ms;\n\tanimation-timing-function: ease-out;\n\tanimation-duration: 350ms;\n}\n.slide.out {\n\t-webkit-transform: translate3d(-100%,0,0);\n\t-webkit-animation-name: slideouttoleft;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n}\n.slide.in {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromright;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromright;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromright;\n}\n.slide.out.reverse {\n\t-webkit-transform: translate3d(100%,0,0);\n\t-webkit-animation-name: slideouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n}\n.slide.in.reverse {\n\t-webkit-transform: translate3d(0,0,0);\n\t-webkit-animation-name: slideinfromleft;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: slideinfromleft;\n\ttransform: translateX(0);\n\tanimation-name: slideinfromleft;\n}\n.slidefade.out {\n\t-webkit-transform: translateX(-100%);\n\t-webkit-animation-name: slideouttoleft;\n\t-webkit-animation-duration: 225ms;\n\t-moz-transform: translateX(-100%);\n\t-moz-animation-name: slideouttoleft;\n\t-moz-animation-duration: 225ms;\n\ttransform: translateX(-100%);\n\tanimation-name: slideouttoleft;\n\tanimation-duration: 225ms;\n}\n.slidefade.in {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n.slidefade.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: slideouttoright;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: slideouttoright;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(100%);\n\tanimation-name: slideouttoright;\n\tanimation-duration: 200ms;\n}\n.slidefade.in.reverse {\n\t-webkit-transform: translateX(0);\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateX(0);\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateX(0);\n\tanimation-name: fadein;\n\tanimation-duration: 200ms;\n}\n/* slide down */\n.slidedown.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slidedown.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfromtop;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfromtop;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfromtop;\n\tanimation-duration: 250ms;\n}\n.slidedown.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slidedown.out.reverse {\n\t-webkit-transform: translateY(-100%);\n\t-webkit-animation-name: slideouttotop;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(-100%);\n\t-moz-animation-name: slideouttotop;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(-100%);\n\tanimation-name: slideouttotop;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfromtop {\n    from { -webkit-transform: translateY(-100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfromtop {\n    from { -moz-transform: translateY(-100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfromtop {\n    from { transform: translateY(-100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttotop {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(-100%); }\n}\n@-moz-keyframes slideouttotop {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(-100%); }\n}\n@keyframes slideouttotop {\n    from { transform: translateY(0); }\n    to { transform: translateY(-100%); }\n}\n/* slide up */\n.slideup.out {\n\t-webkit-animation-name: fadeout;\n\t-webkit-animation-duration: 100ms;\n\t-moz-animation-name: fadeout;\n\t-moz-animation-duration: 100ms;\n\tanimation-name: fadeout;\n\tanimation-duration: 100ms;\n}\n.slideup.in {\n\t-webkit-transform: translateY(0);\n\t-webkit-animation-name: slideinfrombottom;\n\t-webkit-animation-duration: 250ms;\n\t-moz-transform: translateY(0);\n\t-moz-animation-name: slideinfrombottom;\n\t-moz-animation-duration: 250ms;\n\ttransform: translateY(0);\n\tanimation-name: slideinfrombottom;\n\tanimation-duration: 250ms;\n}\n.slideup.in.reverse {\n\t-webkit-animation-name: fadein;\n\t-webkit-animation-duration: 150ms;\n\t-moz-animation-name: fadein;\n\t-moz-animation-duration: 150ms;\n\tanimation-name: fadein;\n\tanimation-duration: 150ms;\n}\n.slideup.out.reverse {\n\t-webkit-transform: translateY(100%);\n\t-webkit-animation-name: slideouttobottom;\n\t-webkit-animation-duration: 200ms;\n\t-moz-transform: translateY(100%);\n\t-moz-animation-name: slideouttobottom;\n\t-moz-animation-duration: 200ms;\n\ttransform: translateY(100%);\n\tanimation-name: slideouttobottom;\n\tanimation-duration: 200ms;\n}\n@-webkit-keyframes slideinfrombottom {\n    from { -webkit-transform: translateY(100%); }\n    to { -webkit-transform: translateY(0); }\n}\n@-moz-keyframes slideinfrombottom {\n    from { -moz-transform: translateY(100%); }\n    to { -moz-transform: translateY(0); }\n}\n@keyframes slideinfrombottom {\n    from { transform: translateY(100%); }\n    to { transform: translateY(0); }\n}\n@-webkit-keyframes slideouttobottom {\n    from { -webkit-transform: translateY(0); }\n    to { -webkit-transform: translateY(100%); }\n}\n@-moz-keyframes slideouttobottom {\n    from { -moz-transform: translateY(0); }\n    to { -moz-transform: translateY(100%); }\n}\n@keyframes slideouttobottom {\n    from { transform: translateY(0); }\n    to { transform: translateY(100%); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-flip {\n\t-webkit-perspective: 1000;\n\t-moz-perspective: 1000;\n\tperspective: 1000;\n\tposition: absolute;\n}\n.flip {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\tbackface-visibility: hidden;\n\ttransform: translateX(0);\n}\n.flip.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 175ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 175ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 175ms;\n}\n.flip.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 225ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 225ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 225ms;\n}\n.flip.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.flip.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* The properties in this rule are only necessary for the 'flip' transition.\n * We need specify the perspective to create a projection matrix. This will add\n * some depth as the element flips. The depth number represents the distance of\n * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n * value.\n */\n.viewport-turn {\n\t-webkit-perspective: 200px;\n\t-moz-perspective: 200px;\n\t-ms-perspective: 200px;\n\tperspective: 200px;\n\tposition: absolute;\n}\n.turn {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n\t-webkit-transform-origin: 0;\n\t\n\t-moz-backface-visibility: hidden;\n\t-moz-transform: translateX(0);\n\t-moz-transform-origin: 0;\n\t\n\tbackface-visibility :hidden;\n\ttransform: translateX(0);\n\ttransform-origin: 0;\n}\n.turn.out {\n\t-webkit-transform: rotateY(-90deg) scale(.9);\n\t-webkit-animation-name: flipouttoleft;\n\t-webkit-animation-duration: 125ms;\n\t-moz-transform: rotateY(-90deg) scale(.9);\n\t-moz-animation-name: flipouttoleft;\n\t-moz-animation-duration: 125ms;\n\ttransform: rotateY(-90deg) scale(.9);\n\tanimation-name: flipouttoleft;\n\tanimation-duration: 125ms;\n}\n.turn.in {\n\t-webkit-animation-name: flipintoright;\n\t-webkit-animation-duration: 250ms;\n\t-moz-animation-name: flipintoright;\n\t-moz-animation-duration: 250ms;\n\tanimation-name: flipintoright;\n\tanimation-duration: 250ms;\n\t\n}\n.turn.out.reverse {\n\t-webkit-transform: rotateY(90deg) scale(.9);\n\t-webkit-animation-name: flipouttoright;\n\t-moz-transform: rotateY(90deg) scale(.9);\n\t-moz-animation-name: flipouttoright;\n\ttransform: rotateY(90deg) scale(.9);\n\tanimation-name: flipouttoright;\n}\n.turn.in.reverse {\n\t-webkit-animation-name: flipintoleft;\n\t-moz-animation-name: flipintoleft;\n\tanimation-name: flipintoleft;\n}\n@-webkit-keyframes flipouttoleft {\n    from { -webkit-transform: rotateY(0); }\n    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoleft {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(-90deg) scale(.9); }\n}\n@keyframes flipouttoleft {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(-90deg) scale(.9); }\n}\n@-webkit-keyframes flipouttoright {\n    from { -webkit-transform: rotateY(0) ; }\n    to { -webkit-transform: rotateY(90deg) scale(.9); }\n}\n@-moz-keyframes flipouttoright {\n    from { -moz-transform: rotateY(0); }\n    to { -moz-transform: rotateY(90deg) scale(.9); }\n}\n@keyframes flipouttoright {\n    from { transform: rotateY(0); }\n    to { transform: rotateY(90deg) scale(.9); }\n}\n@-webkit-keyframes flipintoleft {\n    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoleft {\n    from { -moz-transform: rotateY(-90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoleft {\n    from { transform: rotateY(-90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n@-webkit-keyframes flipintoright {\n    from { -webkit-transform: rotateY(90deg) scale(.9); }\n    to { -webkit-transform: rotateY(0); }\n}\n@-moz-keyframes flipintoright {\n    from { -moz-transform: rotateY(90deg) scale(.9); }\n    to { -moz-transform: rotateY(0); }\n}\n@keyframes flipintoright {\n    from { transform: rotateY(90deg) scale(.9); }\n    to { transform: rotateY(0); }\n}\n/* flow transition */\n.flow {\n\t-webkit-transform-origin: 50% 30%;\n\t-webkit-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\t-moz-transform-origin: 50% 30%;\t\n\t-moz-box-shadow: 0 0 20px rgba(0,0,0,.4);\n\ttransform-origin: 50% 30%;\t\n\tbox-shadow: 0 0 20px rgba(0,0,0,.4);\n}\n.ui-dialog.flow {\n\t-webkit-transform-origin: none;\n\t-webkit-box-shadow: none;\n\t-moz-transform-origin: none;\t\n\t-moz-box-shadow: none;\n\ttransform-origin: none;\t\n\tbox-shadow: none;\n}\n.flow.out {\n\t-webkit-transform: translateX(-100%) scale(.7);\n\t-webkit-animation-name: flowouttoleft;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(-100%) scale(.7);\n\t-moz-animation-name: flowouttoleft;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(-100%) scale(.7);\n\tanimation-name: flowouttoleft;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.in {\n\t-webkit-transform: translateX(0) scale(1);\n\t-webkit-animation-name: flowinfromright;\n\t-webkit-animation-timing-function: ease;\n\t-webkit-animation-duration: 350ms;\n\t-moz-transform: translateX(0) scale(1);\n\t-moz-animation-name: flowinfromright;\n\t-moz-animation-timing-function: ease;\n\t-moz-animation-duration: 350ms;\n\ttransform: translateX(0) scale(1);\n\tanimation-name: flowinfromright;\n\tanimation-timing-function: ease;\n\tanimation-duration: 350ms;\n}\n.flow.out.reverse {\n\t-webkit-transform: translateX(100%);\n\t-webkit-animation-name: flowouttoright;\n\t-moz-transform: translateX(100%);\n\t-moz-animation-name: flowouttoright;\n\ttransform: translateX(100%);\n\tanimation-name: flowouttoright;\n}\n.flow.in.reverse {\n\t-webkit-animation-name: flowinfromleft;\n\t-moz-animation-name: flowinfromleft;\n\tanimation-name: flowinfromleft;\n}\n@-webkit-keyframes flowouttoleft {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(-100%) scale(.7); }\n}\n@-moz-keyframes flowouttoleft {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(-100%) scale(.7); }\n}\n@keyframes flowouttoleft {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(-100%) scale(.7); }\n}\n@-webkit-keyframes flowouttoright {\n    0% { -webkit-transform: translateX(0) scale(1); }\n\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform:  translateX(100%) scale(.7); }\n}\n@-moz-keyframes flowouttoright {\n    0% { -moz-transform: translateX(0) scale(1); }\n\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform:  translateX(100%) scale(.7); }\n}\n@keyframes flowouttoright {\n    0% { transform: translateX(0) scale(1); }\n\t60%, 70% { transform: translateX(0) scale(.7); }\n    100% { transform:  translateX(100%) scale(.7); }\n}\n@-webkit-keyframes flowinfromleft {\n    0% { -webkit-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromleft {\n    0% { -moz-transform: translateX(-100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromleft {\n    0% { transform: translateX(-100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n@-webkit-keyframes flowinfromright {\n    0% { -webkit-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n    100% { -webkit-transform: translateX(0) scale(1); }\n}\n@-moz-keyframes flowinfromright {\n    0% { -moz-transform: translateX(100%) scale(.7); }\n\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n    100% { -moz-transform: translateX(0) scale(1); }\n}\n@keyframes flowinfromright {\n    0% { transform: translateX(100%) scale(.7); }\n\t30%, 40% { transform: translateX(0) scale(.7); }\n    100% { transform: translateX(0) scale(1); }\n}\n.ui-field-contain,\n.ui-mobile fieldset.ui-field-contain {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n\tclear: both;\n\tpadding: .8em 0;\n}\n.ui-field-contain > label ~ [class*=\"ui-\"],\n.ui-field-contain .ui-controlgroup-controls {\n\tmargin: 0;\n}\n.ui-field-contain:last-child {\n\tborder-bottom-width: 0;\n}\n@media (min-width: 28em) {\n\t.ui-field-contain,\n\t.ui-mobile fieldset.ui-field-contain {\n\t\tpadding: 0;\n\t\tmargin: 1em 0;\n\t\tborder-bottom-width: 0;\n\t}\n\t.ui-field-contain:before,\n\t.ui-field-contain:after {\n\t\tcontent: \"\";\n\t\tdisplay: table;\n\t}\n\t.ui-field-contain:after {\n\t\tclear: both;\n\t}\n\t.ui-field-contain > label,\n\t.ui-field-contain .ui-controlgroup-label,\n\t.ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: left;\n\t\twidth: 20%;\n\t\tmargin: .5em 2% 0 0;\n\t}\n\t.ui-popup .ui-field-contain > label,\n\t.ui-popup .ui-field-contain .ui-controlgroup-label,\n\t.ui-popup .ui-field-contain > .ui-rangeslider > label {\n\t\tfloat: none;\n\t\twidth: auto;\n\t\tmargin: 0 0 .4em;\n\t}\n\t.ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: left;\n\t\twidth: 78%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t}\n\t/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n\t.ui-hide-label > label ~ [class*=\"ui-\"],\n\t.ui-hide-label .ui-controlgroup-controls,\n\t.ui-popup .ui-field-contain > label ~ [class*=\"ui-\"],\n\t.ui-popup .ui-field-contain .ui-controlgroup-controls {\n\t\tfloat: none;\n\t\twidth: 100%;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline {\n\t\twidth: auto;\n\t\tmargin-right: .625em;\n\t}\n\t.ui-field-contain > label ~ .ui-btn-inline.ui-btn-icon-notext {\n\t\twidth: 1.75em;\n\t}\n}\n/* content configurations. */\n.ui-grid-a,\n.ui-grid-b,\n.ui-grid-c,\n.ui-grid-d,\n.ui-grid-solo {\n\toverflow: hidden;\n}\n.ui-block-a,\n.ui-block-b,\n.ui-block-c,\n.ui-block-d,\n.ui-block-e {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfloat: left;\n\tmin-height: 1px;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n}\n/* force new row */\n.ui-block-a {\n\tclear: left;\n}\nul.ui-grid-a,\nul.ui-grid-b,\nul.ui-grid-c,\nul.ui-grid-d,\nul.ui-grid-solo,\nli.ui-block-a,\nli.ui-block-b,\nli.ui-block-c,\nli.ui-block-d,\nli.ui-block-e {\n\tmargin-left: 0;\n\tmargin-right: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n/* No margin in grids for 100% width button elements until we can use max-width: fill-available; */\n[class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: 0;\n\tmargin-left: 0;\n}\n[class*=\"ui-block-\"] > .ui-btn,\n[class*=\"ui-block-\"] > .ui-select,\n[class*=\"ui-block-\"] > .ui-checkbox,\n[class*=\"ui-block-\"] > .ui-radio,\n[class*=\"ui-block-\"] > button.ui-btn-inline,\n[class*=\"ui-block-\"] > button.ui-btn-icon-notext,\n.ui-header [class*=\"ui-block-\"] > button.ui-btn,\n.ui-footer [class*=\"ui-block-\"] > button.ui-btn {\n\tmargin-right: .3125em;\n\tmargin-left: .3125em;\n}\n.ui-grid-a > .ui-block-a,\n.ui-grid-a > .ui-block-b {\n\t/* width: 49.95%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 50%;\n}\n.ui-grid-b > .ui-block-a,\n.ui-grid-b > .ui-block-b,\n.ui-grid-b > .ui-block-c {\n\t/* width: 33.25%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 33.333%;\n}\n.ui-grid-c > .ui-block-a,\n.ui-grid-c > .ui-block-b,\n.ui-grid-c > .ui-block-c,\n.ui-grid-c > .ui-block-d {\n\t/* width: 24.925%; IE7 */\n\t/* margin-right: -.5px; BB5 */\n\twidth: 25%;\n}\n.ui-grid-d > .ui-block-a,\n.ui-grid-d > .ui-block-b,\n.ui-grid-d > .ui-block-c,\n.ui-grid-d > .ui-block-d,\n.ui-grid-d > .ui-block-e {\n\t/* width: 19.925%; IE7 */\n\twidth: 20%;\n}\n.ui-grid-solo > .ui-block-a {\n\twidth: 100%;\n\tfloat: none; \n}\n/* preset breakpoint to switch to stacked grid styles below 35em (560px) */\n@media (max-width: 35em) {\n\t.ui-responsive > .ui-block-a,\n\t.ui-responsive > .ui-block-b,\n\t.ui-responsive > .ui-block-c,\n\t.ui-responsive > .ui-block-d,\n\t.ui-responsive > .ui-block-e {\n\t\twidth: 100%; \n\t\tfloat: none; \n\t}\n}\n/* fixed page header & footer configuration */\n.ui-header-fixed,\n.ui-footer-fixed {\n\tleft: 0;\n\tright: 0;\n\twidth: 100%;\n\tposition: fixed;\n\tz-index: 1000;\n}\n.ui-header-fixed {\n\ttop: -1px;\n\tpadding-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden {\n\ttop: 0;\n\tpadding-top: 0;\n}\n.ui-header-fixed .ui-btn-left,\n.ui-header-fixed .ui-btn-right {\n\tmargin-top: 1px;\n}\n.ui-header-fixed.ui-fixed-hidden .ui-btn-left,\n.ui-header-fixed.ui-fixed-hidden .ui-btn-right {\n\tmargin-top: 0;\n}\n.ui-footer-fixed {\n\tbottom: -1px;\n\tpadding-bottom: 1px;\n}\n.ui-footer-fixed.ui-fixed-hidden {\n\tbottom: 0;\n\tpadding-bottom: 0;\n}\n.ui-header-fullscreen,\n.ui-footer-fullscreen {\n\tfilter: Alpha(Opacity=90);\n\topacity: .9;\n}\n/* updatePagePadding() will update the padding to actual height of header and footer. */\n.ui-page-header-fixed {\n\tpadding-top: 2.8125em;\n}\n.ui-page-footer-fixed {\n\tpadding-bottom: 2.8125em;\n}\n.ui-page-header-fullscreen > .ui-content,\n.ui-page-footer-fullscreen > .ui-content {\n\tpadding: 0;\n}\n.ui-fixed-hidden {\n\tposition: absolute;\n}\n/* Tap toggle: hide external fixed footer. See issue #6604 */\n.ui-footer-fixed.ui-fixed-hidden {\n  display: none;\n}\n.ui-page .ui-footer-fixed.ui-fixed-hidden {\n  display: block\n}\n.ui-page-header-fullscreen .ui-fixed-hidden,\n.ui-page-footer-fullscreen .ui-fixed-hidden {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-header-fixed .ui-btn,\n.ui-footer-fixed .ui-btn { \n\tz-index: 10;\n}\n/* workarounds for other widgets */\n.ui-android-2x-fixed .ui-li-has-thumb {\n\t-webkit-transform: translate3d(0,0,0);\n}\n.ui-navbar {\n\tmax-width: 100%;\n}\n.ui-navbar ul:before,\n.ui-navbar ul:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-navbar ul:after {\n\tclear: both;\n}\n.ui-navbar ul {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n\tdisplay: block;\n\tborder: 0;\n\tmax-width: 100%;\n\toverflow: visible;\n}\n.ui-navbar li .ui-btn {\n\tfont-size: 12.5px;\n\tdisplay: block;\n\tmargin: 0;\n\tborder-right-width: 0;\n}\n.ui-header .ui-navbar li button.ui-btn,\n.ui-footer .ui-navbar li button.ui-btn {\n\tmargin: 0;\n\twidth: 100%;\n}\n.ui-navbar .ui-btn:focus {\n\tz-index: 1;\n}\n/* fixes gaps caused by subpixel problem */\n.ui-navbar li:last-child .ui-btn {\n\tmargin-right: -4px;\n}\n.ui-navbar li:last-child .ui-btn:after {\n\tmargin-right: 4px;\n}\n.ui-content .ui-navbar li:last-child .ui-btn,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: 0;\n}\n.ui-content .ui-navbar li:last-child .ui-btn:after,\n.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after {\n\tmargin-right: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after {\n\tmargin-right: 1px;\n}\n.ui-navbar .ui-grid-duo .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-header .ui-navbar .ui-btn,\n.ui-footer .ui-navbar .ui-btn {\n\tborder-top-width: 0;\n\tborder-bottom-width: 0;\n}\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-header .ui-title ~ .ui-navbar .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-btn,\n.ui-header .ui-navbar .ui-grid-duo .ui-btn,\n.ui-footer .ui-navbar .ui-grid-duo .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n\tborder-top-width: 1px;\n}\n/* Hide the native input element */\n.ui-input-btn input {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tbackground: #fff;\n\tbackground: rgba(255,255,255,0);\n\tfilter: Alpha(Opacity=0);\n\topacity: .1;\n\tfont-size: 1px;\n\ttext-indent: -9999px;\n\tz-index: 2;\n}\n/* Fixes IE/WP filter alpha opacity bugs */\n.ui-input-btn.ui-state-disabled input {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible {\n\tmargin: 0 -1em;\n}\n.ui-collapsible-inset,\n.ui-collapsible-set {\n\tmargin: .5em 0;\n}\n.ui-collapsible-heading {\n\tdisplay: block;\n\tmargin: 0;\n\tpadding: 0;\n\tposition: relative;\n}\n.ui-collapsible-heading .ui-btn {\n\ttext-align: left;\n\tmargin: 0;\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n}\n.ui-collapsible-heading .ui-btn-icon-top,\n.ui-collapsible-heading .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-collapsible-inset .ui-collapsible-heading .ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-collapsible-collapsed + .ui-collapsible:not(.ui-collapsible-inset) > .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn {\n\tborder-top-width: 1px;\n}\n.ui-collapsible-heading-status {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-collapsible-content {\n\tdisplay: block;\n\tmargin: 0;\t\n\tpadding: .5em 1em;\n}\n.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 0;\n\tborder-right-width: 0;\n\tborder-top-width: 0;\n\tborder-bottom-width: 1px;\n\tborder-style: solid;\n}\n.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content {\n\tborder-left-width: 1px;\n\tborder-right-width: 1px;\n}\n.ui-collapsible-inset .ui-collapsible-content {\n\tmargin: 0;\n}\n.ui-collapsible-content-collapsed {\n\tdisplay: none;\n}\n.ui-collapsible-set > .ui-collapsible.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-collapsible-heading,\n.ui-collapsible-heading > .ui-btn {\n\t-webkit-border-radius: inherit;\t\n\tborder-radius: inherit;\t\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\t\n\tborder-top-left-radius: inherit;\t\t\n}\n.ui-collapsible-content,\n.ui-collapsible-set .ui-collapsible.ui-last-child {\n\t-webkit-border-bottom-right-radius: inherit;\t\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\t\n\tborder-bottom-left-radius: inherit;\t\t\n}\n.ui-collapsible-themed-content:not(.ui-collapsible-collapsed) > .ui-collapsible-heading {\n\t-webkit-border-bottom-right-radius: 0;\t\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\t\n\tborder-bottom-left-radius: 0;\t\t\n}\n.ui-collapsible-set .ui-collapsible {\n\tmargin: -1px -1em 0;\n}\n.ui-collapsible-set .ui-collapsible-inset {\n\tmargin: -1px 0 0;\n}\n.ui-collapsible-set .ui-collapsible.ui-first-child {\n\tmargin-top: 0;\n}\n.ui-controlgroup,\nfieldset.ui-controlgroup {\n\tpadding: 0;\n\tmargin: .5em 0;\n}\n.ui-field-contain .ui-controlgroup,\n.ui-field-contain fieldset.ui-controlgroup {\n\tmargin: 0;\n}\n.ui-mini .ui-controlgroup-label {\n\tfont-size: 16px;\n}\n.ui-controlgroup.ui-mini .ui-btn-icon-notext,\n.ui-controlgroup .ui-mini.ui-btn-icon-notext {\n\tfont-size: inherit;\n}\n.ui-controlgroup-controls .ui-btn,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-select {\n\tmargin: 0;\n}\n.ui-controlgroup-controls .ui-btn:focus,\n.ui-controlgroup-controls .ui-btn.ui-focus {\n\tz-index: 1;\n}\n.ui-controlgroup-controls li {\n\tlist-style: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:before,\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n\tclear: both;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls li > .ui-btn,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select {\n\tfloat: left;\n\tclear: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,\n.ui-controlgroup-controls .ui-btn-icon-notext {\n\twidth: auto;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,\n.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext {\n\twidth: 1.5em;\n}\n .ui-controlgroup-controls .ui-btn-icon-notext {\n\theight: auto;\n\tpadding: .7em 1em;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-bottom-width: 1px;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn {\n\tborder-right-width: 0;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child {\n\tborder-right-width: 1px;\n}\n.ui-controlgroup-controls .ui-btn-corner-all,\n.ui-controlgroup-controls .ui-btn.ui-corner-all {\n\t-webkit-border-radius: 0;\n\tborder-radius: 0;\n}\n.ui-controlgroup-controls,\n.ui-controlgroup-controls .ui-radio,\n.ui-controlgroup-controls .ui-checkbox,\n.ui-controlgroup-controls .ui-select,\n.ui-controlgroup-controls li {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-controlgroup-vertical .ui-btn.ui-last-child {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-first-child {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-controlgroup-horizontal .ui-btn.ui-last-child {\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-controlgroup-controls a.ui-shadow:not(:focus),\n.ui-controlgroup-controls button.ui-shadow:not(:focus),\n.ui-controlgroup-controls div.ui-shadow:not(.ui-focus) {\n\t-moz-box-shadow: none;\n\t-webkit-box-shadow: none;\n\tbox-shadow: none;\n}\n/* Fixes legend not wrapping on IE10 */\n.ui-controlgroup-label legend {\n\tmax-width: 100%;\n}\n.ui-controlgroup-controls > label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-dialog {\n\t background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */\n}\n.ui-dialog-contain {\n\twidth: 92.5%;\n\tmax-width: 500px;\n\tmargin: 10% auto 1em auto;\n\tpadding: 0;\n\tposition: relative;\n\ttop: -1em;\n}\n.ui-dialog-contain > .ui-header, \n.ui-dialog-contain > .ui-content, \n.ui-dialog-contain > .ui-footer { \n\tdisplay: block;\n\tposition: relative; \n\twidth: auto;\n\tmargin: 0;\n}\n.ui-dialog-contain > .ui-header {\n\toverflow: hidden;\n\tz-index: 10; \n\tpadding: 0;\n\tborder-top-width: 0;\n}\n.ui-dialog-contain > .ui-footer {\n\tz-index: 10; \n\tpadding: 0 1em; \n\tborder-bottom-width: 0;\n}\n.ui-popup-open .ui-header-fixed,\n.ui-popup-open .ui-footer-fixed {\n\tposition: absolute !important; /* See issues #4816, #4844 and #4874 and popup.js */\n}\n.ui-popup-screen {\n\tbackground-image: url(\"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\"); /* Necessary to set some form of background to ensure element is clickable in IE6/7. While legacy IE won't understand the data-URI'd image, it ensures no additional requests occur in all other browsers with little overhead. */\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 1px;\n\tposition: absolute;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 1099;\n}\n.ui-popup-screen.in {\n\topacity: 0.5;\n\tfilter: Alpha(Opacity=50);\n}\n.ui-popup-screen.out {\n\topacity: 0;\n\tfilter: Alpha(Opacity=0);\n}\n.ui-popup-container {\n\tz-index: 1100;\n\tdisplay: inline-block;\n\tposition: absolute;\n\tpadding: 0;\n\toutline: 0;\n}\n.ui-popup {\n\tposition: relative;\n}\n.ui-popup.ui-body-inherit {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-hidden {\n\tleft: 0;\n\ttop: 0;\n\tposition: absolute !important;\n\tvisibility: hidden;\n}\n.ui-popup-truncate {\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-popup.ui-content,\n.ui-popup .ui-content {\n\toverflow: visible;\n}\n.ui-popup > .ui-header {\n\tborder-top-width: 0;\n}\n.ui-popup > .ui-footer {\n\tborder-bottom-width: 0;\n}\n.ui-popup > p,\n.ui-popup > h1,\n.ui-popup > h2,\n.ui-popup > h3,\n.ui-popup > h4,\n.ui-popup > h5,\n.ui-popup > h6 {\n\tmargin: .5em .4375em;\n}\n.ui-popup > span {\n\tdisplay: block;\n\tmargin: .5em .4375em;\n}\n.ui-popup-container .ui-content > p,\n.ui-popup-container .ui-content > h1,\n.ui-popup-container .ui-content > h2,\n.ui-popup-container .ui-content > h3,\n.ui-popup-container .ui-content > h4,\n.ui-popup-container .ui-content > h5,\n.ui-popup-container .ui-content > h6 {\n\tmargin: .5em 0;\n}\n.ui-popup-container .ui-content > span {\n\tmargin: 0;\n}\n.ui-popup-container .ui-content > p:first-child,\n.ui-popup-container .ui-content > h1:first-child,\n.ui-popup-container .ui-content > h2:first-child,\n.ui-popup-container .ui-content > h3:first-child,\n.ui-popup-container .ui-content > h4:first-child,\n.ui-popup-container .ui-content > h5:first-child,\n.ui-popup-container .ui-content > h6:first-child {\n\tmargin-top: 0;\n}\n.ui-popup-container .ui-content > p:last-child,\n.ui-popup-container .ui-content > h1:last-child,\n.ui-popup-container .ui-content > h2:last-child,\n.ui-popup-container .ui-content > h3:last-child,\n.ui-popup-container .ui-content > h4:last-child,\n.ui-popup-container .ui-content > h5:last-child,\n.ui-popup-container .ui-content > h6:last-child {\n\tmargin-bottom: 0;\n}\n.ui-popup > img {\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tvertical-align: middle;\n}\n.ui-popup:not(.ui-content) > img:only-child,\n.ui-popup:not(.ui-content) > .ui-btn-left:first-child + img:last-child,\n.ui-popup:not(.ui-content) > .ui-btn-right:first-child + img:last-child {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-popup iframe {\n\tvertical-align: middle;\n}\n.ui-popup > .ui-btn-left,\n.ui-popup > .ui-btn-right {\n\tposition: absolute; \n\ttop: -11px;\n\tmargin: 0;\n\tz-index: 1101;\n}\n.ui-popup > .ui-btn-left {\n\tleft: -11px;\n}\n.ui-popup > .ui-btn-right {\n\tright: -11px;\n}\n/* Dimensions related to the popup arrow\n-----------------------------------------------------------------------------------------------------------*/\n/* desired triangle height: 10px */\n/**\n * guide for the arrow - its width, height, and offset are theme-dependent and\n * should be expessed as left, right, top, bottom, so that the element bearing\n * such a class becomes stretched inside its parent position: relative element.\n * The left/top/right/bottom specified below should reflect the corresponding\n * border radii and so it leaves room for the shadow:\n *     ..--------------------..\n *   .\"        ^ top           \".\n *  /          v                 \\\n * |     +------------------+     |\n * |     |                  |     |\n * | left|                  |right|\n * |<--->|                  |<--->|\n * |     +------------------+     |\n *  \\          ^                 /\n *   `.        v bottom        .'\n *     \"\"--------------------\"\"\n * The idea is that the top/left of the arrow container box does not move to a\n * coordinate smaller than the top/left of the guide and the right/bottom of\n * the arrow container box does not move to a coordinate larger than the\n * bottom/right of the guide. This will help us avoid the following situation:\n *        ..--------------------..\n *      .\"        ^ top           \".\n *   /|/          v                 \\\n *  / |     +------------------+     |\n *  \\ |     |                  |     |\n *   \\| left|                  |right|\n *    |<--->|                  |<--->|\n *    |     +------------------+     |\n *     \\          ^                 /\n *      `.        v bottom        .'\n *        \"\"--------------------\"\"\n * The arrow should not receive a top/left coordinate such that it is too close\n * to one of the corners, because then at first the shadow of the arrow and,\n * given a coordinate even closer to the corner, even the body of the arrow will\n * \"stick out\" of the corner of the popup. The guide provides a hint to the\n * arrow positioning code as to which range of values is acceptable for the\n * arrow container's top/left coordinate.\n **/\n.ui-popup-arrow-container {\n\twidth: 20px;\n\theight: 20px;\n}\n/* aside from the \"infinities\" (-1000,2000), triangle height is used */\n.ui-popup-arrow-container.ui-popup-arrow-l {\n\tleft: -10px;\n\tclip: rect(-1000px,10px,2000px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-t {\n\ttop: -10px;\n\tclip: rect(-1000px,2000px,10px,-1000px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-r {\n\tright: -10px;\n\tclip: rect(-1000px,2000px,2000px,10px);\n}\n.ui-popup-arrow-container.ui-popup-arrow-b {\n\tbottom: -10px;\n\tclip: rect(10px,2000px,1000px,-1000px);\n}\n/**\n * For each side, the arrow is twice the desired size and its corner is aligned\n * with the edge of the container:\n *                                           \n *           /\\         /\\                +----+       /\\\n *          /  \\       /  \\               | /\\ |top   /  \\\n *      +----+  \\     /  +----+       +-->|/  \\|     /    \\\n *  left| /  |   \\   /   |  \\ |right  |   |    |    /      \\\n *      |/   |    \\ /    |   \\|       |  /|    |\\  /        \\\n *      |\\   |    / \\    |   /|       | / +----+ \\ \\ +----+ /\n *      | \\  |   /   \\   |  / |       | \\        /  \\|    |/\n *      +----+  /     \\  +----+       |  \\      /    |    |\n *       ^  \\  /       \\  /  ^        |   \\    /  +->|\\  /|\n *       |   \\/         \\/   |        |    \\  /   |  | \\/ |bottom\n *       |                   |        |     \\/    |  +----+\n *       +-------------------+--------+-----------+\n *                           |\n *                    arrow container\n *                     (clips arrow)\n **/\n.ui-popup-arrow-container .ui-popup-arrow {\n\t/* (4*desired triangle height)/sqrt(2) - does not account for border - centred within the outer rectangle */\n\twidth: 28.284271247px;\n\theight: 28.284271247px;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: 5.857864376px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow {\n\tleft: -4.142135623px;\n\ttop: -14.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow {\n\tleft: 5.857864376px;\n\ttop: -4.142135623px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow {\n\tleft: -14.142135623px;\n\ttop: -4.142135623px;\n}\n/* Fix rotation center for oldIE - see http://www.useragentman.com/IETransformsTranslator/ */\n.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -7.0710678118654755px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow {\n    margin-left: -5.857864376269049px;\n    margin-top: -4.142135623730951px;\n}\n \n.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow {\n    margin-left: -7.0710678118654755px;\n    margin-top: -5.857864376269049px;\n}\n.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow {\n    margin-left: -4.142135623730951px;\n    margin-top: -5.857864376269049px;\n}\n/* structure */\n.ui-popup > .ui-popup-arrow-guide {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\ttop: 0;\n\tbottom: 0;\n\tvisibility: hidden;\n}\n.ui-popup-arrow-container {\n\tposition: absolute;\n}\n.ui-popup-arrow {\n\t-webkit-transform: rotate(45deg);\n\t-moz-transform: rotate(45deg);\n\t-ms-transform: rotate(45deg);\n\ttransform: rotate(45deg);\n\tposition: absolute;\n\toverflow: hidden;\n\tbox-sizing: border-box;\n}\n.ui-popup-arrow-container.ie .ui-popup-arrow {\n\t-ms-filter: \"progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod='auto expand')\";\n\tfilter: progid:DXImageTransform.Microsoft.Matrix(\n\t      \tM11=0.7071067811865474,\n        \tM12=-0.7071067811865477,\n        \tM21=0.7071067811865477,\n        \tM22=0.7071067811865474,\n        \tSizingMethod='auto expand');\n}\n.ui-checkbox,\n.ui-radio {\n\tmargin: .5em 0;\n\tposition: relative;\n}\n.ui-checkbox .ui-btn,\n.ui-radio .ui-btn {\n\tmargin: 0;\n\ttext-align: left;\n\twhite-space: normal; /* Nowrap + ellipsis doesn't work on label. Issue #1419. */\n\tz-index: 2;\n}\n.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,\n.ui-controlgroup .ui-radio .ui-btn.ui-focus {\n\tz-index: 3;\n}\n.ui-checkbox .ui-btn-icon-top,\n.ui-radio .ui-btn-icon-top,\n.ui-checkbox .ui-btn-icon-bottom,\n.ui-radio .ui-btn-icon-bottom {\n\ttext-align: center;\n}\n.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,\n.ui-controlgroup-horizontal .ui-radio .ui-btn:after {\n\tcontent: none;\n\tdisplay: none;\n}\n/* Native input positioning */\n.ui-checkbox input,\n.ui-radio input {\n\tposition: absolute;\n\tleft: .466em;\n\ttop: 50%;\n\twidth: 22px;\n\theight: 22px;\n\tmargin: -11px 0 0 0;\n\toutline: 0 !important;\n\tz-index: 1;\n}\n.ui-controlgroup-horizontal .ui-checkbox input,\n.ui-controlgroup-horizontal .ui-radio input {\n\tleft: 50%;\n\tmargin-left: -9px;\n}\n.ui-checkbox input:disabled,\n.ui-radio input:disabled {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select {\n\tmargin-top: .5em;\n\tmargin-bottom: .5em; /* no shorthand for margin because it would override margin-right for inline selects */\n\tposition: relative;\n}\n.ui-select > select {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-select .ui-btn {\n\tmargin: 0;\n\topacity: 1; /* Fixes #2588: When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select (including \"inherit\") without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */\n}\n.ui-select .ui-btn select {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\tmin-height: 1.5em;\n\tmin-height: 100%;\n\theight: 3em;\n\tmax-height: 100%;\n\toutline: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tcursor: pointer;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n\tz-index: 2;\n}\n@-moz-document url-prefix() {\n\t.ui-select .ui-btn select {\n\t\topacity: 0.0001;\n\t}\n}\n/* Display none because of issues with IE/WP's filter alpha opacity */\n.ui-select .ui-state-disabled select {\n\tdisplay: none;\n}\n/* Because we add all classes of the select and option elements to the span... */ \n.ui-select span.ui-state-disabled {\n\tfilter: Alpha(Opacity=100);\n\topacity: 1;\n}\n.ui-select .ui-btn.ui-select-nativeonly {\n\tborder-radius: 0;\n\tborder: 0;\n}\n.ui-select .ui-btn.ui-select-nativeonly select {\n\topacity: 1;\n\ttext-indent: 0;\n\tdisplay: block;\n}\n/* ui-li-count is styled in the listview CSS. We set padding and offset here because select supports icon position while listview doesn't. */\n.ui-select .ui-li-has-count.ui-btn {\n\tpadding-right: 2.8125em;\n}\n.ui-select .ui-li-has-count.ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-select .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n/* We set the rules for the span as well to fix an issue on Chrome with text-overflow ellipsis for the button in combination with text-align center. */\n.ui-select .ui-btn > span:not(.ui-li-count) {\n\tdisplay: block;\n\ttext-overflow: ellipsis;\n\toverflow: hidden !important;\n\twhite-space: nowrap;\n}\n.ui-selectmenu.ui-popup {\n\tmin-width: 11em;\n}\n.ui-selectmenu .ui-dialog-contain {\n\toverflow: hidden;\n}\n.ui-selectmenu .ui-header {\n\tmargin: 0;\n\tpadding: 0;\n\tborder-width: 0;\n}\n.ui-selectmenu.ui-dialog .ui-header {\n\tz-index: 1;\n\tposition: relative;\n}\n.ui-selectmenu.ui-popup .ui-header {\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n}\n/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button.  this shim's content in there */\n.ui-selectmenu.ui-popup .ui-header h1:after {\n\tcontent: '.';\n\tvisibility: hidden;\n}\n.ui-selectmenu .ui-header .ui-title {\n\tmargin: 0 2.875em;\n}\n.ui-selectmenu.ui-dialog .ui-content {\n\toverflow: visible;\n\tz-index: 1;\n}\n.ui-selectmenu .ui-selectmenu-list {\n\tmargin: 0;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-header:not(.ui-screen-hidden) + .ui-selectmenu-list {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-top-left-radius: 0;\n\tborder-top-left-radius: 0;\n}\n.ui-header.ui-screen-hidden + .ui-selectmenu-list li.ui-first-child .ui-btn {\n\tborder-top-width: 0;\n}\n.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-selectmenu .ui-btn.ui-li-divider {\n\tcursor: default;\n}\n.ui-selectmenu .ui-selectmenu-placeholder {\n\tdisplay: none;\n}\n.ui-listview,\n.ui-listview > li {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n.ui-content .ui-listview,\n.ui-panel-inner > .ui-listview {\n\tmargin: -1em;\n}\n.ui-content .ui-listview-inset,\n.ui-panel-inner > .ui-listview-inset {\n\tmargin: 1em 0;\n}\n.ui-collapsible-content > .ui-listview {\n\tmargin: -.5em -1em;\n}\n.ui-collapsible-content > .ui-listview-inset {\n\tmargin: .5em 0;\n}\n.ui-listview > li {\n\tdisplay: block;\n\tposition: relative;\n\toverflow: visible;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tmargin: 0;\n\tdisplay: block;\n\tposition: relative;\n\ttext-align: left;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li > .ui-btn:focus {\n\tz-index: 1;\n}\n.ui-listview > .ui-li-static,\n.ui-listview > .ui-li-divider,\n.ui-listview > li > a.ui-btn {\n\tborder-width: 1px 0 0 0;\n\tborder-style: solid;\n}\n.ui-listview-inset > .ui-li-static,\n.ui-listview-inset > .ui-li-divider,\n.ui-listview-inset > li > a.ui-btn {\n\tborder-right-width: 1px;\n\tborder-left-width: 1px;\n}\n.ui-listview > .ui-li-static.ui-last-child,\n.ui-listview > .ui-li-divider.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 1px;\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 0;\n}\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child,\n.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child > a.ui-btn {\n\tborder-bottom-width: 0;\n}\n.ui-listview > li.ui-first-child,\n.ui-listview > li.ui-first-child > a.ui-btn {\n\t-webkit-border-top-right-radius: inherit;\t\n\tborder-top-right-radius: inherit;\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\n}\n.ui-listview > li.ui-last-child,\n.ui-listview > li.ui-last-child > a.ui-btn {\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\n}\n.ui-listview > li.ui-li-has-alt > a.ui-btn {\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n.ui-listview > li.ui-first-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-top-left-radius: 0;\t\n\tborder-top-left-radius: 0;\n\t-webkit-border-top-right-radius: inherit;\n\tborder-top-right-radius: inherit;\n}\n.ui-listview > li.ui-last-child > a.ui-btn + a.ui-btn {\n\t-webkit-border-bottom-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n\t-webkit-border-bottom-right-radius: inherit;\n\tborder-bottom-right-radius: inherit;\n}\n.ui-listview > li.ui-first-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-top-left-radius: inherit;\n\tborder-top-left-radius: inherit;\t\n}\n.ui-listview > li.ui-last-child img:first-child:not(.ui-li-icon) {\n\t-webkit-border-bottom-left-radius: inherit;\n\tborder-bottom-left-radius: inherit;\t\n}\n.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\t\n}\n.ui-listview > .ui-li-static {\n\tpadding: .7em 1em;\n}\n.ui-listview > .ui-li-divider {\n\tpadding: .5em 1.143em;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tcursor: default;\n\toutline: 0; /* Dividers in custom selectmenus have tabindex */\n}\n.ui-listview > .ui-li-has-count > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-count,\n.ui-listview > .ui-li-divider.ui-li-has-count {\n\tpadding-right: 2.8125em;\n}\n.ui-listview > .ui-li-has-count > .ui-btn-icon-right {\n\tpadding-right: 4.6875em;\n}\n.ui-listview > .ui-li-has-thumb > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-thumb {\n\tmin-height: 3.625em;\n\tpadding-left: 6.25em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > .ui-btn,\n.ui-listview > .ui-li-static.ui-li-has-icon {\n\tmin-height: 1.25em;\n\tpadding-left: 2.5em;\n}\n/* Used by both listview and custom multiple select button */\n.ui-li-count {\n\tposition: absolute;\n\tfont-size: 12.5px;\n\tfont-weight: bold;\n\ttext-align: center;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tpadding: 0 .48em;\n\tline-height: 1.6em;\n\tmin-height: 1.6em;\n\tmin-width: .64em;\n\tright: .8em;\n\ttop: 50%;\n\tmargin-top: -.88em;\n}\n.ui-listview .ui-btn-icon-right .ui-li-count {\n\tright: 3.2em;\n}\n.ui-listview .ui-li-has-thumb > img:first-child,\n.ui-listview .ui-li-has-thumb > .ui-btn > img:first-child,\n.ui-listview .ui-li-has-thumb .ui-li-thumb {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\tmax-height: 5em;\n\tmax-width: 5em;\n}\n/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n.ui-listview > .ui-li-has-icon > img:first-child,\n.ui-listview > .ui-li-has-icon > .ui-btn > img:first-child {\n\tposition: absolute;\n\tleft: .625em;\n\ttop: .9em;\n\tmax-height: 1em;\n\tmax-width: 1em;\n}\n.ui-listview > li h1,\n.ui-listview > li h2,\n.ui-listview > li h3,\n.ui-listview > li h4,\n.ui-listview > li h5,\n.ui-listview > li h6 {\n\tfont-size: 1em;\n\tfont-weight: bold;\n\tdisplay: block;\n\tmargin: .45em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview > li p {\n\tfont-size: .75em;\n\tfont-weight: normal;\n\tdisplay: block;\n\tmargin: .6em 0;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n.ui-listview .ui-li-aside {\n\tposition: absolute;\n\ttop: 1em;\n\tright: 3.333em;\n\tmargin: 0;\n\ttext-align: right;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn {\n\tmargin-right: 2.5em;\n\tborder-right-width: 0;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tposition: absolute;\n\twidth: 2.5em;\n\theight: 100%;\n\tmin-height: auto;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-left-width: 1px;\n\ttop: 0;\n\tright: 0;\n\tmargin: 0;\n\tpadding: 0;\n\tz-index: 2;\n}\n.ui-listview-inset > li.ui-li-has-alt > .ui-btn + .ui-btn {\n\tborder-right-width: 1px;\n}\n.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn:focus {\n\tz-index: 3;\n}\nol.ui-listview,\nol.ui-listview > .ui-li-divider {\n\tcounter-reset: listnumbering;\n}\nol.ui-listview > li > .ui-btn,\nol.ui-listview > li.ui-li-static {\n\tvertical-align: middle;\n}\nol.ui-listview > li > .ui-btn:first-child:before,\nol.ui-listview > li.ui-li-static:before,\nol.ui-listview > li.ui-field-contain > label:before,\nol.ui-listview > li.ui-field-contain > .ui-controlgroup-label:before {\n\tdisplay: inline-block;\n\tfont-size: .9em;\n\tfont-weight: normal;\n\tpadding-right: .3em;\n\tmin-width: 1.4em;\n\tline-height: 1.5;\n\tvertical-align: middle;\n\tcounter-increment: listnumbering;\n\tcontent: counter(listnumbering) \".\";\n}\nol.ui-listview > li.ui-field-contain:before {\n\tcontent: none;\n\tdisplay: none;\n}\nol.ui-listview > li h1:first-child,\nol.ui-listview > li h2:first-child,\nol.ui-listview > li h3:first-child,\nol.ui-listview > li h4:first-child,\nol.ui-listview > li h5:first-child,\nol.ui-listview > li h6:first-child,\nol.ui-listview > li p:first-child,\nol.ui-listview > li img:first-child + * {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n}\nol.ui-listview > li h1:first-child ~ *,\nol.ui-listview > li h2:first-child ~ *,\nol.ui-listview > li h3:first-child ~ *,\nol.ui-listview > li h4:first-child ~ *,\nol.ui-listview > li h5:first-child ~ *,\nol.ui-listview > li h6:first-child ~ *,\nol.ui-listview > li p:first-child ~ *,\nol.ui-listview > li img:first-child + * ~ * {\n\tmargin-top: 0;\n\ttext-indent: 2.04em; /* (1.4em + .3em) * .9em / .75em */\n}\nhtml .ui-filterable + .ui-listview,\nhtml .ui-filterable.ui-listview {\n\tmargin-top: .5em;\n}\n.ui-collapsible-content > form.ui-filterable {\n\tmargin-top: -.5em;\n}\n.ui-collapsible-content > .ui-input-search.ui-filterable {\n\tmargin-top: 0;\n}\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n\tborder-top-width: 1px;\n}\ndiv.ui-slider {\n\theight: 30px;\n\tmargin: .5em 0;\n\tpadding: 0;\n\t-ms-touch-action: pan-y pinch-zoom double-tap-zoom;\n}\ndiv.ui-slider:before,\ndiv.ui-slider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\ndiv.ui-slider:after {\n\tclear: both;\n}\ninput.ui-slider-input {\n\tdisplay: block;\n\tfloat: left;\n\tfont-size: 14px;\n\tfont-weight: bold;\n\tmargin: 0;\n\tpadding: 4px;\n\twidth: 40px;\n\theight: 20px;\n\tline-height: 20px;\n\tborder-width: 1px;\n\tborder-style: solid;\n\toutline: 0;\n\ttext-align: center;\n\tvertical-align: text-bottom;\n\t-webkit-appearance: none;\n\t-moz-appearance: none;\n\tappearance: none;\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-slider-input::-webkit-outer-spin-button,\n.ui-slider-input::-webkit-inner-spin-button {\n\t-webkit-appearance: none;\n\tmargin: 0;\n}\n.ui-slider-track {\n\tposition: relative;\n\toverflow: visible;\n\tborder-width: 1px;\n\tborder-style: solid;\n\theight: 15px;\n\tmargin: 0 15px 0 68px;\n\ttop: 6px;\n}\n.ui-slider-track.ui-mini {\n\theight: 12px;\n\ttop: 8px;\n}\n.ui-slider-track .ui-slider-bg {\n\theight: 100%;\n}\n/* High level of specificity to override button margins in grids */\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tposition: absolute;\n\tz-index: 1;\n\ttop: 50%;\n\twidth: 28px;\n\theight: 28px;\n\tmargin: -15px 0 0 -15px;\n\toutline: 0;\n\tpadding: 0;\n}\n.ui-slider-track.ui-mini .ui-slider-handle {\n\theight: 14px;\n\twidth: 14px;\n\tmargin: -8px 0 0 -8px;\n}\nselect.ui-slider-switch {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\ndiv.ui-slider-switch {\n\tdisplay: inline-block;\n\theight: 32px;\n\twidth: 5.8em;\n\ttop: 0;\n}\n/* reset the clearfix */\ndiv.ui-slider-switch:before,\ndiv.ui-slider-switch:after {\n\tdisplay: none;\n\tclear: none;\n}\ndiv.ui-slider-switch.ui-mini {\n\theight: 29px;\n\ttop: 0;\n}\n.ui-slider-inneroffset {\n\tmargin: 0 16px;\n\tposition: relative;\n\tz-index: 1;\n}\n.ui-slider-switch.ui-mini .ui-slider-inneroffset {\n\tmargin: 0 15px 0 14px;\n}\n.ui-slider-switch .ui-btn.ui-slider-handle {\n\tmargin: 1px 0 0 -15px;\n}\n.ui-slider-switch.ui-mini .ui-slider-handle {\n\twidth: 25px;\n\theight: 25px;\n\tmargin: 1px 0 0 -13px;\n\tpadding: 0;\n}\n.ui-slider-handle-snapping {\n\t-webkit-transition: left 70ms linear;\n\t-moz-transition: left 70ms linear;\n\ttransition: left 70ms linear;\n}\n.ui-slider-switch .ui-slider-label {\n\tposition: absolute;\n\ttext-align: center;\n\twidth: 100%;\n\toverflow: hidden;\n\tfont-size: 16px;\n\ttop: 0;\n\tline-height: 2;\n\tmin-height: 100%;\n\twhite-space: nowrap;\n\tcursor: pointer;\n}\n.ui-slider-switch.ui-mini .ui-slider-label {\n\tfont-size: 14px;\n}\n.ui-slider-switch .ui-slider-label-a {\n\tz-index: 1;\n\tleft: 0;\n\ttext-indent: -1.5em;\n}\n.ui-slider-switch .ui-slider-label-b {\n\tz-index: 0;\n\tright: 0;\n\ttext-indent: 1.5em;\n}\n/* The corner radii for ui-slider-switch/track can be specified in theme CSS. The bg and handle inherits. */\n.ui-slider-track .ui-slider-bg,\n.ui-slider-switch .ui-slider-label,\n.ui-slider-switch .ui-slider-inneroffset,\n.ui-slider-handle {\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\n.ui-field-contain div.ui-slider-switch {\n\tmargin: 0;\n}\n/* ui-hide-label deprecated in 1.4. TODO: Remove in 1.5 */\n.ui-field-contain div.ui-slider-switch,\n.ui-field-contain.ui-hide-label div.ui-slider-switch,\nhtml .ui-popup .ui-field-contain div.ui-slider-switch {\n\tdisplay: inline-block;\n\twidth: 5.8em;\n}\n/* slider tooltip\n-----------------------------------------------------------------------------------------------------------*/\n.ui-slider-popup {\n\twidth: 64px;\n\theight: 64px;\n\tfont-size: 36px;\n\tpadding-top: 14px;\n\topacity: 0.8;\n}\n.ui-slider-popup {\n\tposition: absolute !important;\n\ttext-align: center;\n\tz-index: 100;\n}\n.ui-slider-track .ui-btn.ui-slider-handle {\n\tfont-size: .9em;\n\tline-height: 30px;\n}\n.ui-rangeslider {\n\tmargin: .5em 0;\n}\n.ui-rangeslider:before,\n.ui-rangeslider:after {\n\tcontent: \"\";\n\tdisplay: table;\n}\n.ui-rangeslider:after {\n\tclear: both;\n}\n.ui-rangeslider .ui-slider-input.ui-rangeslider-last {\n\tfloat: right;\n}\n.ui-rangeslider .ui-rangeslider-sliders {\n\tposition: relative;\n\toverflow: visible;\n\theight: 30px;\n\tmargin: 0 68px;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track {\n\tposition: absolute;\n\ttop: 6px;\n\tright: 0;\n\tleft: 0;\n\tmargin: 0;\n}\n.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track {\n\ttop: 8px;\n}\n.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg {\n\tdisplay: none;\n}\n.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\tbackground-color: transparent;\n\tbackground: none;\n\tborder-width: 0;\n\theight: 0;\n}\n/* this makes ie6 and ie7 set height to 0 to fix z-index problem */\nhtml >/**/body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 15px;\n\tborder-width: 1px;\n}\nhtml >/**/body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child {\n\theight: 12px;\n}\n/* Hide the second label (the first is moved outside the div) */\ndiv.ui-rangeslider label {\n\tposition: absolute !important;\n\theight: 1px;\n\twidth: 1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-field-contain .ui-rangeslider input.ui-slider-input,\n.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,\n.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,\n.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders {\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n}\n.ui-input-text,\n.ui-input-search {\n\tmargin: .5em 0;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-mini {\n\tmargin: .446em;\n}\n.ui-input-text input,\n.ui-input-search input,\ntextarea.ui-input-text {\n\tpadding: .4em;\n\tline-height: 1.4em;\n\tdisplay: block;\n\twidth: 100%;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\toutline: 0;\n}\n.ui-input-text input,\n.ui-input-search input {\n\tmargin: 0;\n\tmin-height: 2.2em;\n\ttext-align: left; /* Opera aligns type=\"date\" right by default */\n\tborder: 0;\n\tbackground: transparent none;\n\t-webkit-appearance: none;\n\t-webkit-border-radius: inherit;\n\tborder-radius: inherit;\n}\ntextarea.ui-input-text {\n\toverflow: auto;\n\tresize: vertical;\n}\n.ui-mini .ui-input-text input,\n.ui-mini .ui-input-search input,\n.ui-input-text.ui-mini input,\n.ui-input-search.ui-mini input,\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tfont-size: 14px;\n}\n/* Same margin for mini textareas as other mini sized widgets (12.5/14 * 0.5em) */\n.ui-mini textarea.ui-input-text,\ntextarea.ui-mini {\n\tmargin: .446em 0;\n}\n.ui-input-has-clear,\n.ui-input-search {\n\tposition: relative;\n}\n/* Padding on the div instead of input because of browser spinners etc. */\n.ui-input-has-clear {\n\tpadding-right: 2.375em;\n}\n.ui-mini.ui-input-has-clear {\n\tpadding-right: 2.923em;\n}\n.ui-input-has-clear input {\n\tpadding-right: 0;\n\t/* Autofill on Chrome has bg color so we unset corners right as well. */\n\t-webkit-border-top-right-radius: 0;\n\tborder-top-right-radius: 0;\n\t-webkit-border-bottom-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n/* Search icon */\n.ui-input-search input {\n\tpadding-left: 1.75em;\n}\n.ui-input-search:after {\n\tposition: absolute;\n\tleft: .3125em;\n\ttop: 50%;\n\tmargin-top: -7px;\n\tcontent: \"\";\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\twidth: 14px;\n\theight: 14px;\n\tfilter: Alpha(Opacity=50);\n\topacity: .5;\n}\n.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,\n.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear {\n\tposition: absolute;\n\tright: 0;\n\ttop: 50%;\n\tmargin: -14px .3125em 0;\n\tborder: 0;\n\tbackground-color: transparent;\n}\n.ui-input-search .ui-input-clear-hidden,\n.ui-input-text .ui-input-clear-hidden {\n\tdisplay: none;\n}\n/* Resolves issue #5166: Added to support issue introduced in Firefox 15. We can likely remove this in the future. */\n.ui-input-text input::-moz-placeholder,\n.ui-input-search input::-moz-placeholder,\ntextarea.ui-input-text::-moz-placeholder {\n\tcolor: #aaa;\n}\n/* Same for IE10 */\n.ui-input-text input:-ms-input-placeholder,\n.ui-input-search input:-ms-input-placeholder,\ntextarea.ui-input-text:-ms-input-placeholder {\n\tcolor: #aaa;\n}\n/* Resolves issue #5131: Width of textinput depends on its type,\nfor Android 4.1 */\n.ui-input-text input[type=number]::-webkit-outer-spin-button {\n\tmargin: 0;\n}\n/* Resolves issue #5756: Textinput in IE10 has a default clear button */\n.ui-input-text input::-ms-clear,\n.ui-input-search input::-ms-clear {\n\tdisplay: none;\n}\n.ui-input-text input:focus,\n.ui-input-search input:focus {\n\t-webkit-box-shadow: none;\n\t-moz-box-shadow: none;\n\tbox-shadow: none;\n}\ntextarea.ui-input-text.ui-textinput-autogrow {\n\toverflow: hidden;\n}\n.ui-textinput-autogrow-resize {\n\t-webkit-transition: height 0.25s;\n\t-o-transition: height 0.25s;\n\t-moz-transition: height 0.25s;\n\ttransition: height 0.25s;\n}\n.ui-flipswitch {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\twidth: 5.875em; /* Override this and padding-left in next rule if you use labels other than \"on/off\" and need more space */\n\theight: 1.875em;\n\tborder-width: 1px;\n\tborder-style: solid;\n\tmargin: .5em 0;\n\toverflow: hidden;\n\t-webkit-transition-property: padding, width, background-color, color, border-color;\n\t-moz-transition-property: padding, width, background-color, color, border-color;\n\t-o-transition-property: padding, width, background-color, color, border-color;\n\ttransition-property: padding, width, background-color, color, border-color;\n\t-webkit-transition-duration: 100ms;\n\t-moz-transition-duration: 100ms;\n\t-o-transition-duration: 100ms;\n\ttransition-duration: 100ms;\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\tcursor: pointer;\n}\n.ui-flipswitch.ui-flipswitch-active {\n\tpadding-left: 4em;  /* Override this and width in previous rule if you use labels other than \"on/off\" and need more space */\n\twidth: 1.875em;\n}\n.ui-flipswitch-input {\n\tposition: absolute;\n\theight: 1px;\n\twidth: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(1px,1px,1px,1px);\n\tborder: 0;\n\toutline: 0;\n\tfilter: Alpha(Opacity=0);\n\topacity: 0;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on,\n.ui-flipswitch .ui-flipswitch-off {\n\tfloat: left;\n\theight: 1.75em;\n\tmargin: .0625em;\n\tline-height: 1.65em;\n}\n.ui-flipswitch .ui-btn.ui-flipswitch-on {\n\twidth: 1.75em;\n\tpadding: 0;\n\ttext-indent: -2.6em; /* Override this to center text if you use a label other than \"on\" */\n\ttext-align: left;\n\tborder-width: 1px;\n\tborder-style: solid;\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tborder-radius: inherit;\n\toverflow: visible;\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n.ui-flipswitch .ui-flipswitch-off {\n\tpadding: 1px;\n\ttext-indent: 1em; /* Override this to center text if you use a label other than \"off\" */\n}\n/* Override field container CSS to prevent the flipswitch from becomming full width */\nhtml .ui-field-contain > label + .ui-flipswitch,\nhtml .ui-popup .ui-field-contain > label + .ui-flipswitch {\n\tdisplay: inline-block;\n\twidth: 5.875em; /* If you override the width for .ui-flipswitch you should repeat the same value here */\n\t-webkit-box-sizing: content-box;\n\t-moz-box-sizing: content-box;\n\tbox-sizing: content-box;\n}\n.ui-field-contain .ui-flipswitch.ui-flipswitch-active,\n.ui-popup .ui-field-contain .ui-flipswitch.ui-flipswitch-active {\n\twidth: 1.875em;\n}\n.ui-table {\n\tborder: 0;\n\tborder-collapse: collapse;\n\tpadding: 0;\n\twidth: 100%;\n}\n.ui-table th,\n.ui-table td {\n\tline-height: 1.5em;\n\ttext-align: left;\n\tpadding: .4em .5em;\n\tvertical-align:top;\n}\n.ui-table th .ui-btn,\n.ui-table td .ui-btn {\n\tline-height: normal;\n}\n.ui-table th {\n\tfont-weight: bold;\n}\n.ui-table caption {\n\ttext-align: left;\n\tmargin-bottom: 1.4em;\n\topacity: .5;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-columntoggle-btn {\n\tfloat: right;\n\tmargin-bottom: .8em;\n}\n/* Remove top/bottom margins around the fieldcontain on check list */\n.ui-table-columntoggle-popup fieldset {\n\tmargin:0;\n}\n.ui-table-columntoggle {\n\tclear: both;\n}\n/* Hide all prioritized columns by default */\n@media only all {\n\tth.ui-table-priority-6,\n\ttd.ui-table-priority-6,\n\tth.ui-table-priority-5,\n\ttd.ui-table-priority-5,\n\tth.ui-table-priority-4,\n\ttd.ui-table-priority-4,\n\tth.ui-table-priority-3,\n\ttd.ui-table-priority-3,\n\tth.ui-table-priority-2,\n\ttd.ui-table-priority-2,\n\tth.ui-table-priority-1,\n\ttd.ui-table-priority-1 {\n\t\tdisplay: none;\n\t}\n}\n/* Preset breakpoints if \".ui-responsive\" class added to table */\n/* Show priority 1 at 320px (20em x 16px) */\n@media screen and (min-width: 20em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-1 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 2 at 480px (30em x 16px) */\n@media screen and (min-width: 30em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-2 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 3 at 640px (40em x 16px) */\n@media screen and (min-width: 40em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-3 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 4 at 800px (50em x 16px) */\n@media screen and (min-width: 50em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-4 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 5 at 960px (60em x 16px) */\n@media screen and (min-width: 60em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-5 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Show priority 6 at 1,120px (70em x 16px) */\n@media screen and (min-width: 70em) {\n\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,\n\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-6 {\n\t\tdisplay: table-cell;\n\t}\n}\n/* Unchecked manually: Always hide */\n.ui-table-columntoggle th.ui-table-cell-hidden,\n.ui-table-columntoggle td.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden {\n\tdisplay: none;\n}\n/* Checked manually: Always show */\n.ui-table-columntoggle th.ui-table-cell-visible,\n.ui-table-columntoggle td.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,\n.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible {\n\tdisplay: table-cell;\n}\n/*\n Styles for the table columntoggle mode\n*/\n.ui-table-reflow td .ui-table-cell-label,\n.ui-table-reflow th .ui-table-cell-label { \n\tdisplay: none;\n}\n/* Mobile first styles: Begin with the stacked presentation at narrow widths */ \n@media only all {\n\t/* Hide the table headers */ \n\t.ui-table-reflow thead td, \n\t.ui-table-reflow thead th {\n\t\tdisplay: none;\n\t}\n\t/* Show the table cells as a block level element */ \n\t.ui-table-reflow td,\n\t.ui-table-reflow th { \n\t\ttext-align: left;\n\t\tdisplay: block;\n\t}\n\t/* Add a fair amount of top margin to visually separate each row when stacked */  \n\t.ui-table-reflow tbody th {\n\t\tmargin-top: 3em;\n\t}\n\t/* Make the label elements a percentage width */ \n\t.ui-table-reflow td .ui-table-cell-label,\n\t.ui-table-reflow th .ui-table-cell-label { \n\t\tpadding: .4em; \n\t\tmin-width: 30%; \n\t\tdisplay: inline-block;\n\t\tmargin: -.4em 1em -.4em -.4em;\n\t}\n\t/* For grouped headers, have a different style to visually separate the levels by classing the first label in each col group */ \n\t.ui-table-reflow th .ui-table-cell-label-top,\n\t.ui-table-reflow td .ui-table-cell-label-top {\n\t\tdisplay: block;\n\t\tpadding: .4em 0;\n\t\tmargin: .4em 0;\n\t\ttext-transform: uppercase;\n\t\tfont-size: .9em;\n\t\tfont-weight: normal;\n\t}\n}\n/* Breakpoint to show as a standard table at 560px (35em x 16px) or wider */ \n@media ( min-width: 35em ) {\n\t/* Show the table header rows */ \n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th,\n\t.ui-table-reflow.ui-responsive tbody th,\n\t.ui-table-reflow.ui-responsive tbody td,\n\t.ui-table-reflow.ui-responsive thead td,\n\t.ui-table-reflow.ui-responsive thead th {\n\t\tdisplay: table-cell;\n\t\tmargin: 0;\n\t}\n\t/* Hide the labels in each cell */ \n\t.ui-table-reflow.ui-responsive td .ui-table-cell-label,\n\t.ui-table-reflow.ui-responsive th .ui-table-cell-label { \n\t\tdisplay: none;\n\t}\n}\n/* Hack to make IE9 and WP7.5 treat cells like block level elements, scoped to ui-responsive class */ \n/* Applied in a max-width media query up to the table layout breakpoint so we don't need to negate this*/ \n@media ( max-width: 35em ) {\n\t.ui-table-reflow.ui-responsive td,\n\t.ui-table-reflow.ui-responsive th {\n\t\twidth: 100%;\n\t\t-webkit-box-sizing: border-box;\n\t\t-moz-box-sizing: border-box;\n\t\tbox-sizing: border-box;\n\t\tfloat: left;\n\t\tclear: left;\n\t}\n}\n/* Panel */\n.ui-panel {\n\twidth: 17em;\n\tmin-height: 100%;\n\tmax-height: none;\n\tborder-width: 0;\n\tposition: absolute;\n\ttop: 0;\n\tdisplay: block;\n}\n.ui-panel-closed {\n\twidth: 0;\n\tmax-height: 100%;\n\toverflow: hidden;\n\tvisibility: hidden;\n\tleft: 0;\n\tclip: rect(1px,1px,1px,1px);\n}\n.ui-panel-fixed {\n\tposition: fixed;\n\tbottom: -1px; /* Fixes gap on Chrome for Android */\n\tpadding-bottom: 1px;\n}\n.ui-panel-display-reveal {\n\tz-index: 1;\n}\n.ui-panel-display-push {\n\tz-index: 999;\n}\n.ui-panel-display-overlay {\n\tz-index: 1001; /* Fixed toolbars have z-index 1000 */\n}\n.ui-panel-inner {\n\tpadding: 1em;\n}\n/* Container, page and wrapper */\n.ui-panel-page-container {\n\toverflow-x: visible;\n}\n.ui-panel-page-container-themed .ui-page-active {\n\tbackground: none;\n}\n.ui-panel-wrapper {\n\tposition: relative;\n\tmin-height: inherit;\n\tborder: 0;\n\toverflow-x: hidden;\n\tz-index: 999;\n}\n/* Fixed toolbars */\n.ui-panel-fixed-toolbar {\n\toverflow-x: hidden;\n}\n/* Dismiss */\n.ui-panel-dismiss {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\theight: 100%;\n\tz-index: 1002;\n\tdisplay: none;\n}\n.ui-panel-dismiss-open {\n\tdisplay: block;\n}\n/* Animate class is added to panel, wrapper and fixed toolbars */\n.ui-panel-animate {\n\t-webkit-transition: -webkit-transform 300ms ease;\n\t-webkit-transition-duration: 300ms;\n\t-moz-transition: -moz-transform 300ms ease;\n\ttransition: transform 300ms ease;\n}\n/* Fix for Windows Phone issue #6349: unset the transition for transforms in case of fixed toolbars. */\n@media screen and ( max-device-width: 768px ) {\n\t.ui-page-header-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-page-footer-fixed .ui-panel-animate.ui-panel-wrapper,\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: none;\n\t}\n\t/* We need a transitionend event ... */\n\t.ui-panel-animate.ui-panel-fixed-toolbar {\n\t\t-ms-transition: -ms-transform 1ms;\n\t\t-ms-transform: rotate(0deg);\n\t}\n}\n/* Hardware acceleration for smoother transitions on WebKit browsers */\n.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal) {\n\t-webkit-backface-visibility: hidden;\n\t-webkit-transform: translate3d(0,0,0);\n}\n/* Panel positioning (for overlay and push) */\n/* Panel left closed */\n.ui-panel-position-left {\n\tleft: -17em;\n}\n/* Panel left closed animated */\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-left.ui-panel-display-push {\n\tleft: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Panel left open */\n.ui-panel-position-left.ui-panel-display-reveal, /* Unset \"panel left closed\" for reveal */\n.ui-panel-open.ui-panel-position-left {\n\tleft: 0;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Panel right closed */\n.ui-panel-position-right {\n\tright: -17em;\n}\n/* Panel right closed animated */\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-position-right.ui-panel-display-push {\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-position-right.ui-panel-display-reveal, /* Unset \"panel right closed\" for reveal */\n.ui-panel-position-right.ui-panel-open {\n\tright: 0;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,\n.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\t-webkit-transform: translate3d(0,0,0);\n\ttransform: translate3d(0,0,0);\n\t-moz-transform: none;\n}\n/* Wrapper and fixed toolbars positioning (for reveal and push) */\n/* Panel left open */\n.ui-panel-page-content-position-left {\n\tleft: 17em;\n\tright: -17em;\n}\n/* Panel left open animated */\n.ui-panel-animate.ui-panel-page-content-position-left {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(17em,0,0);\n\t-moz-transform: translate3d(17em,0,0);\n\ttransform: translate3d(17em,0,0);\n}\n/* Panel right open */\n.ui-panel-page-content-position-right {\n\tleft: -17em;\n\tright: 17em;\n}\n/* Panel right open animated */\n.ui-panel-animate.ui-panel-page-content-position-right {\n\tleft: 0;\n\tright: 0;\n\t-webkit-transform: translate3d(-17em,0,0);\n\t-moz-transform: translate3d(-17em,0,0);\n\ttransform: translate3d(-17em,0,0);\n}\n/* Dismiss model open */\n.ui-panel-dismiss-open.ui-panel-dismiss-position-left {\n\tleft: 17em;\n}\n.ui-panel-dismiss-open.ui-panel-dismiss-position-right {\n\tright: 17em;\n}\n/* Shadows and borders */\n.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-reveal {\n\t-webkit-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-display-overlay {\n\t-webkit-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: 5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-position-right.ui-panel-display-overlay {\n\t-webkit-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\t-moz-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n\tbox-shadow: -5px 0 5px rgba(0,0,0,.15);\n}\n.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n\tborder-right-width: 1px;\n\tmargin-right: -1px;\n}\n.ui-panel-page-content-position-left.ui-panel-page-content-display-push {\n\tmargin-left: 1px;\n\twidth: auto;\n}\n.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n\tborder-left-width: 1px;\n\tmargin-left: -1px;\n}\n.ui-panel-page-content-position-right.ui-panel-page-content-display-push {\n\tmargin-right: 1px;\n\twidth: auto;\n}\n/* Responsive: wrap on wide viewports once open */\n@media (min-width:55em) {\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left {\n\t\tmargin-right: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right {\n\t\tmargin-left: 17em;\n\t}\n\t.ui-responsive-panel .ui-panel-page-content-open {\n\t\twidth: auto;\t\n\t}\n\t.ui-responsive-panel .ui-panel-dismiss-display-push,\n\t.ui-responsive-panel.ui-page-active ~ .ui-panel-dismiss-display-push {\n\t\tdisplay: none;\n\t}\n}\n.ui-tabs {\n\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n\tpadding: .2em;\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.mobile/jquery.mobile.theme-1.4.5.css",
    "content": "/*!\n* jQuery Mobile 1.4.5\n* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC\n* http://jquerymobile.com\n*\n* Copyright 2010, 2014 jQuery Foundation, Inc. and othercontributors\n* Released under the MIT license.\n* http://jquery.org/license\n*\n*/\n\n\n/* Globals */\n/* Font\n-----------------------------------------------------------------------------------------------------------*/\nhtml {\n\tfont-size: 100%;\n}\nbody,\ninput,\nselect,\ntextarea,\nbutton,\n.ui-btn {\n\tfont-size: 1em;\n\tline-height: 1.3;\n\tfont-family: sans-serif /*{global-font-family}*/;\n}\nlegend,\n.ui-input-text input,\n.ui-input-search input {\n\tcolor: inherit;\n\ttext-shadow: inherit;\n}\n/* Form labels (overrides font-weight bold in bars, and mini font-size) */\n.ui-mobile label,\ndiv.ui-controlgroup-label {\n\tfont-weight: normal;\n\tfont-size: 16px;\n}\n/* Separators\n-----------------------------------------------------------------------------------------------------------*/\n/* Field contain separator (< 28em) */\n.ui-field-contain {\n\tborder-bottom-color: #828282;\n\tborder-bottom-color: rgba(0,0,0,.15);\n\tborder-bottom-width: 1px;\n\tborder-bottom-style: solid;\n}\n/* Table opt-in classes: strokes between each row, and alternating row stripes */\n/* Classes table-stroke and table-stripe are deprecated in 1.4. */\n.table-stroke thead th,\n.table-stripe thead th,\n.table-stripe tbody tr:last-child {\n\tborder-bottom: 1px solid #d6d6d6; /* non-RGBA fallback */\n\tborder-bottom: 1px solid rgba(0,0,0,.1);\n}\n.table-stroke tbody th,\n.table-stroke tbody td {\n\tborder-bottom: 1px solid #e6e6e6; /* non-RGBA fallback  */\n\tborder-bottom: 1px solid rgba(0,0,0,.05);\n}\n.table-stripe.table-stroke tbody tr:last-child th,\n.table-stripe.table-stroke tbody tr:last-child td {\n\tborder-bottom: 0;\n}\n.table-stripe tbody tr:nth-child(odd) td,\n.table-stripe tbody tr:nth-child(odd) th {\n\tbackground-color: #eeeeee; /* non-RGBA fallback  */\n\tbackground-color: rgba(0,0,0,.04);\n}\n/* Buttons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn,\nlabel.ui-btn {\n\tfont-weight: bold;\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n.ui-btn {\n\ttext-decoration: none !important;\n}\n.ui-btn-active {\n\tcursor: pointer;\n}\n/* Corner rounding\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-btn-corner-all deprecated in 1.4 */\n.ui-corner-all {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-blocks}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-blocks}*/;\n}\n/* Buttons */\n.ui-btn-corner-all,\n.ui-btn.ui-corner-all,\n/* Slider track */\n.ui-slider-track.ui-corner-all,\n/* Flipswitch */\n.ui-flipswitch.ui-corner-all,\n/* Count bubble */\n.ui-li-count {\n\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-buttons}*/;\n\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-buttons}*/;\n}\n/* Icon-only buttons */\n.ui-btn-icon-notext.ui-btn-corner-all,\n.ui-btn-icon-notext.ui-corner-all {\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Radius clip workaround for cleaning up corner trapping */\n.ui-btn-corner-all,\n.ui-corner-all {\n\t-webkit-background-clip: padding;\n\tbackground-clip: padding-box;\n}\n/* Popup arrow */\n.ui-popup.ui-corner-all > .ui-popup-arrow-guide {\n\tleft: .6em /*{global-radii-blocks}*/;\n\tright: .6em /*{global-radii-blocks}*/;\n\ttop: .6em /*{global-radii-blocks}*/;\n\tbottom: .6em /*{global-radii-blocks}*/;\n}\n/* Shadow\n-----------------------------------------------------------------------------------------------------------*/\n.ui-shadow {\n\t-webkit-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n\tbox-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\t\t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n}\n.ui-shadow-inset {\n\t-webkit-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\t-moz-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n\tbox-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n}\n.ui-overlay-shadow {\n\t-webkit-box-shadow: 0 0 12px \t\trgba(0,0,0,.6);\n\t-moz-box-shadow: 0 0 12px \t\t\trgba(0,0,0,.6);\n\tbox-shadow: 0 0 12px \t\t\t\trgba(0,0,0,.6);\n}\n/* Icons\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn-icon-left:after,\n.ui-btn-icon-right:after,\n.ui-btn-icon-top:after,\n.ui-btn-icon-bottom:after,\n.ui-btn-icon-notext:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.3) /*{global-icon-disc}*/;\n\tbackground-position: center center;\n\tbackground-repeat: no-repeat;\n\t-webkit-border-radius: 1em;\n\tborder-radius: 1em;\n}\n/* Alt icons */\n.ui-alt-icon.ui-btn:after,\n.ui-alt-icon .ui-btn:after,\nhtml .ui-alt-icon.ui-checkbox-off:after,\nhtml .ui-alt-icon.ui-radio-off:after,\nhtml .ui-alt-icon .ui-checkbox-off:after,\nhtml .ui-alt-icon .ui-radio-off:after {\n\tbackground-color: \t\t\t\t\t#666 /*{global-icon-color}*/;\n\tbackground-color: \t\t\t\t\trgba(0,0,0,.15) /*{global-icon-disc}*/;\n}\n/* No disc */\n.ui-nodisc-icon.ui-btn:after,\n.ui-nodisc-icon .ui-btn:after {\n\tbackground-color: transparent;\n}\n/* Icon shadow */\n.ui-shadow-icon.ui-btn:after,\n.ui-shadow-icon .ui-btn:after {\n\t-webkit-box-shadow: 0 1px 0 \t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\t-moz-box-shadow: 0 1px 0 \t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n\tbox-shadow: 0 1px 0 \t\t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n}\n/* Checkbox and radio */\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after,\n.ui-btn.ui-radio-off:after,\n.ui-btn.ui-radio-on:after {\n\tdisplay: block;\n\twidth: 18px;\n\theight: 18px;\n\tmargin: -9px 2px 0 2px;\n}\n.ui-checkbox-off:after,\n.ui-btn.ui-radio-off:after {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n}\n.ui-btn.ui-checkbox-off:after,\n.ui-btn.ui-checkbox-on:after {\n\t-webkit-border-radius: .1875em;\n\tborder-radius: .1875em;\n}\n.ui-btn.ui-checkbox-off:after {\n\tbackground-color: #666;\n\tbackground-color: rgba(0,0,0,.3);\n}\n.ui-radio .ui-btn.ui-radio-on:after {\n\tbackground-image: none;\n\tbackground-color: #fff;\n\twidth: 8px;\n\theight: 8px;\n\tborder-width: 5px;\n\tborder-style: solid; \n}\n.ui-alt-icon.ui-btn.ui-radio-on:after,\n.ui-alt-icon .ui-btn.ui-radio-on:after {\n\tbackground-color: #000;\n}\n/* Loader */\n.ui-icon-loading {\n\tbackground: url(\"images/ajax-loader.gif\");\n\tbackground-size: 2.875em 2.875em;\n}\n/* Swatches */\n/* A\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-a,\n.ui-page-theme-a .ui-bar-inherit,\nhtml .ui-bar-a .ui-bar-inherit,\nhtml .ui-body-a .ui-bar-inherit,\nhtml body .ui-group-theme-a .ui-bar-inherit {\n\tbackground-color: \t\t\t#e9e9e9 /*{a-bar-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bar-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bar-color}*/;\n\ttext-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 0 /*{a-bar-shadow-radius}*/ \t#eee /*{a-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-a,\n.ui-page-theme-a,\n.ui-page-theme-a .ui-panel-wrapper {\n\tbackground-color: \t\t\t#f9f9f9 /*{a-page-background-color}*/;\n\tborder-color:\t \t\t#bbb /*{a-page-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-page-color}*/;\n\ttext-shadow: 0 /*{a-page-shadow-x}*/ 1px /*{a-page-shadow-y}*/ 0 /*{a-page-shadow-radius}*/ \t#f3f3f3 /*{a-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-a,\n.ui-page-theme-a .ui-body-inherit,\nhtml .ui-bar-a .ui-body-inherit,\nhtml .ui-body-a .ui-body-inherit,\nhtml body .ui-group-theme-a .ui-body-inherit,\nhtml .ui-panel-page-container-a {\n\tbackground-color: \t\t\t#fff /*{a-body-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-body-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-body-color}*/;\n\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ \t#f3f3f3 /*{a-body-shadow-color}*/;\n}\n.ui-body-a {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-a a,\nhtml .ui-bar-a a,\nhtml .ui-body-a a,\nhtml body .ui-group-theme-a a {\n\tcolor: #3388cc /*{a-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-a a:visited,\nhtml .ui-bar-a a:visited,\nhtml .ui-body-a a:visited,\nhtml body .ui-group-theme-a a:visited {\n    color: #3388cc /*{a-link-visited}*/;\n}\n.ui-page-theme-a a:hover,\nhtml .ui-bar-a a:hover,\nhtml .ui-body-a a:hover,\nhtml body .ui-group-theme-a a:hover {\n\tcolor: #005599 /*{a-link-hover}*/;\n}\n.ui-page-theme-a a:active,\nhtml .ui-bar-a a:active,\nhtml .ui-body-a a:active,\nhtml body .ui-group-theme-a a:active {\n\tcolor: #005599 /*{a-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-a .ui-btn,\nhtml .ui-bar-a .ui-btn,\nhtml .ui-body-a .ui-btn,\nhtml body .ui-group-theme-a .ui-btn,\nhtml head + body .ui-btn.ui-btn-a,\n/* Button visited */\n.ui-page-theme-a .ui-btn:visited,\nhtml .ui-bar-a .ui-btn:visited,\nhtml .ui-body-a .ui-btn:visited,\nhtml body .ui-group-theme-a .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-a:visited {\n\tbackground-color: \t\t\t#f6f6f6 /*{a-bup-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bup-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bup-color}*/;\n\ttext-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #f3f3f3 /*{a-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-a .ui-btn:hover,\nhtml .ui-bar-a .ui-btn:hover,\nhtml .ui-body-a .ui-btn:hover,\nhtml body .ui-group-theme-a .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-a:hover {\n\tbackground-color: \t\t\t#ededed /*{a-bhover-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bhover-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bhover-color}*/;\n\ttext-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #f3f3f3 /*{a-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-a .ui-btn:active,\nhtml .ui-bar-a .ui-btn:active,\nhtml .ui-body-a .ui-btn:active,\nhtml body .ui-group-theme-a .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-a:active {\n\tbackground-color: \t\t\t#e8e8e8 /*{a-bdown-background-color}*/;\n\tborder-color:\t \t\t#ddd /*{a-bdown-border}*/;\n\tcolor: \t\t\t\t\t#333 /*{a-bdown-color}*/;\n\ttext-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #f3f3f3 /*{a-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-a .ui-btn.ui-btn-active,\nhtml .ui-bar-a .ui-btn.ui-btn-active,\nhtml .ui-body-a .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-a .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-a.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-a .ui-checkbox-on:after,\nhtml .ui-bar-a .ui-checkbox-on:after,\nhtml .ui-body-a .ui-checkbox-on:after,\nhtml body .ui-group-theme-a .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-a:after,\n/* Active flipswitch background */\n.ui-page-theme-a .ui-flipswitch-active,\nhtml .ui-bar-a .ui-flipswitch-active,\nhtml .ui-body-a .ui-flipswitch-active,\nhtml body .ui-group-theme-a .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-a .ui-slider-track .ui-btn-active,\nhtml .ui-bar-a .ui-slider-track .ui-btn-active,\nhtml .ui-body-a .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-a .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-a .ui-btn-active {\n\tbackground-color: \t\t#3388cc /*{a-active-background-color}*/;\n\tborder-color:\t \t\t#3388cc /*{a-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{a-active-color}*/;\n\ttext-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #005599 /*{a-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-a .ui-radio-on:after,\nhtml .ui-bar-a .ui-radio-on:after,\nhtml .ui-body-a .ui-radio-on:after,\nhtml body .ui-group-theme-a .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-a:after {\n\tborder-color:\t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-a .ui-btn:focus,\nhtml .ui-bar-a .ui-btn:focus,\nhtml .ui-body-a .ui-btn:focus,\nhtml body .ui-group-theme-a .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-a:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-a .ui-focus,\nhtml .ui-bar-a .ui-focus,\nhtml .ui-body-a .ui-focus,\nhtml body .ui-group-theme-a .ui-focus,\nhtml head + body .ui-btn-a.ui-focus,\nhtml head + body .ui-body-a.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#3388cc /*{a-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#3388cc /*{a-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#3388cc /*{a-active-background-color}*/;\n}\n/* B\n-----------------------------------------------------------------------------------------------------------*/\n/* Bar: Toolbars, dividers, slider track */\n.ui-bar-b,\n.ui-page-theme-b .ui-bar-inherit,\nhtml .ui-bar-b .ui-bar-inherit,\nhtml .ui-body-b .ui-bar-inherit,\nhtml body .ui-group-theme-b .ui-bar-inherit {\n\tbackground-color: \t\t\t#1d1d1d /*{b-bar-background-color}*/;\n\tborder-color:\t \t\t#1b1b1b /*{b-bar-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bar-color}*/;\n\ttext-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 0 /*{b-bar-shadow-radius}*/ \t#111 /*{b-bar-shadow-color}*/;\n\tfont-weight: bold;\n}\n.ui-bar-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Page and overlay */\n.ui-overlay-b,\n.ui-page-theme-b,\n.ui-page-theme-b .ui-panel-wrapper {\n\tbackground-color: \t\t\t#252525 /*{b-page-background-color}*/;\n\tborder-color:\t \t\t#454545 /*{b-page-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-page-color}*/;\n\ttext-shadow: 0 /*{b-page-shadow-x}*/ 1px /*{b-page-shadow-y}*/ 0 /*{b-page-shadow-radius}*/ \t#111 /*{b-page-shadow-color}*/;\n}\n/* Body: Read-only lists, text inputs, collapsible content */\n.ui-body-b,\n.ui-page-theme-b .ui-body-inherit,\nhtml .ui-bar-b .ui-body-inherit,\nhtml .ui-body-b .ui-body-inherit,\nhtml body .ui-group-theme-b .ui-body-inherit,\nhtml .ui-panel-page-container-b {\n\tbackground-color: \t\t\t#2a2a2a /*{b-body-background-color}*/;\n\tborder-color:\t \t\t#1d1d1d /*{b-body-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-body-color}*/;\n\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ \t#111 /*{b-body-shadow-color}*/;\n}\n.ui-body-b {\n\tborder-width: 1px;\n\tborder-style: solid;\n}\n/* Links */\n.ui-page-theme-b a,\nhtml .ui-bar-b a,\nhtml .ui-body-b a,\nhtml body .ui-group-theme-b a {\n\tcolor: #22aadd /*{b-link-color}*/;\n\tfont-weight: bold;\n}\n.ui-page-theme-b a:visited,\nhtml .ui-bar-b a:visited,\nhtml .ui-body-b a:visited,\nhtml body .ui-group-theme-b a:visited {\n    color: #22aadd /*{b-link-visited}*/;\n}\n.ui-page-theme-b a:hover,\nhtml .ui-bar-b a:hover,\nhtml .ui-body-b a:hover,\nhtml body .ui-group-theme-b a:hover {\n\tcolor: #0088bb /*{b-link-hover}*/;\n}\n.ui-page-theme-b a:active,\nhtml .ui-bar-b a:active,\nhtml .ui-body-b a:active,\nhtml body .ui-group-theme-b a:active {\n\tcolor: #0088bb /*{b-link-active}*/;\n}\n/* Button up */\n.ui-page-theme-b .ui-btn,\nhtml .ui-bar-b .ui-btn,\nhtml .ui-body-b .ui-btn,\nhtml body .ui-group-theme-b .ui-btn,\nhtml head + body .ui-btn.ui-btn-b,\n/* Button visited */\n.ui-page-theme-b .ui-btn:visited,\nhtml .ui-bar-b .ui-btn:visited,\nhtml .ui-body-b .ui-btn:visited,\nhtml body .ui-group-theme-b .ui-btn:visited,\nhtml head + body .ui-btn.ui-btn-b:visited {\n\tbackground-color: \t\t\t#333 /*{b-bup-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bup-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n\ttext-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #111 /*{b-bup-shadow-color}*/;\n}\n/* Button hover */\n.ui-page-theme-b .ui-btn:hover,\nhtml .ui-bar-b .ui-btn:hover,\nhtml .ui-body-b .ui-btn:hover,\nhtml body .ui-group-theme-b .ui-btn:hover,\nhtml head + body .ui-btn.ui-btn-b:hover {\n\tbackground-color: \t\t\t#373737 /*{b-bhover-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bhover-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n\ttext-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #111 /*{b-bhover-shadow-color}*/;\n}\n/* Button down */\n.ui-page-theme-b .ui-btn:active,\nhtml .ui-bar-b .ui-btn:active,\nhtml .ui-body-b .ui-btn:active,\nhtml body .ui-group-theme-b .ui-btn:active,\nhtml head + body .ui-btn.ui-btn-b:active {\n\tbackground-color: \t\t\t#404040 /*{b-bdown-background-color}*/;\n\tborder-color:\t \t\t#1f1f1f /*{b-bdown-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n\ttext-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #111 /*{b-bdown-shadow-color}*/;\n}\n/* Active button */\n.ui-page-theme-b .ui-btn.ui-btn-active,\nhtml .ui-bar-b .ui-btn.ui-btn-active,\nhtml .ui-body-b .ui-btn.ui-btn-active,\nhtml body .ui-group-theme-b .ui-btn.ui-btn-active,\nhtml head + body .ui-btn.ui-btn-b.ui-btn-active,\n/* Active checkbox icon */\n.ui-page-theme-b .ui-checkbox-on:after,\nhtml .ui-bar-b .ui-checkbox-on:after,\nhtml .ui-body-b .ui-checkbox-on:after,\nhtml body .ui-group-theme-b .ui-checkbox-on:after,\n.ui-btn.ui-checkbox-on.ui-btn-b:after,\n/* Active flipswitch background */\n.ui-page-theme-b .ui-flipswitch-active,\nhtml .ui-bar-b .ui-flipswitch-active,\nhtml .ui-body-b .ui-flipswitch-active,\nhtml body .ui-group-theme-b .ui-flipswitch-active,\nhtml body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,\n/* Active slider track */\n.ui-page-theme-b .ui-slider-track .ui-btn-active,\nhtml .ui-bar-b .ui-slider-track .ui-btn-active,\nhtml .ui-body-b .ui-slider-track .ui-btn-active,\nhtml body .ui-group-theme-b .ui-slider-track .ui-btn-active,\nhtml body div.ui-slider-track.ui-body-b .ui-btn-active {\n\tbackground-color: \t\t#22aadd /*{b-active-background-color}*/;\n\tborder-color:\t \t\t#22aadd /*{b-active-border}*/;\n\tcolor: \t\t\t\t\t#fff /*{b-active-color}*/;\n\ttext-shadow: 0 /*{b-active-shadow-x}*/ 1px /*{b-active-shadow-y}*/ 0 /*{b-active-shadow-radius}*/ #0088bb /*{b-active-shadow-color}*/;\n}\n/* Active radio button icon */\n.ui-page-theme-b .ui-radio-on:after,\nhtml .ui-bar-b .ui-radio-on:after,\nhtml .ui-body-b .ui-radio-on:after,\nhtml body .ui-group-theme-b .ui-radio-on:after,\n.ui-btn.ui-radio-on.ui-btn-b:after {\n\tborder-color:\t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Focus */\n.ui-page-theme-b .ui-btn:focus,\nhtml .ui-bar-b .ui-btn:focus,\nhtml .ui-body-b .ui-btn:focus,\nhtml body .ui-group-theme-b .ui-btn:focus,\nhtml head + body .ui-btn.ui-btn-b:focus,\n/* Focus buttons and text inputs with div wrap */\n.ui-page-theme-b .ui-focus,\nhtml .ui-bar-b .ui-focus,\nhtml .ui-body-b .ui-focus,\nhtml body .ui-group-theme-b .ui-focus,\nhtml head + body .ui-btn-b.ui-focus,\nhtml head + body .ui-body-b.ui-focus {\n\t-webkit-box-shadow: 0 0 12px \t#22aadd /*{b-active-background-color}*/;\n\t-moz-box-shadow: 0 0 12px \t\t#22aadd /*{b-active-background-color}*/;\n\tbox-shadow: 0 0 12px \t\t\t#22aadd /*{b-active-background-color}*/;\n}\n/* Structure */\n/* Disabled\n-----------------------------------------------------------------------------------------------------------*/\n/* Class ui-disabled deprecated in 1.4. :disabled not supported by IE8 so we use [disabled] */\n.ui-disabled,\n.ui-state-disabled,\nbutton[disabled],\n.ui-select .ui-btn.ui-state-disabled {\n\tfilter: Alpha(Opacity=30);\n\topacity: .3;\n\tcursor: default !important;\n\tpointer-events: none;\n}\n/* Focus state outline\n-----------------------------------------------------------------------------------------------------------*/\n.ui-btn:focus,\n.ui-btn.ui-focus {\n\toutline: 0;\n}\n/* Unset box-shadow in browsers that don't do it right */\n.ui-noboxshadow .ui-shadow,\n.ui-noboxshadow .ui-shadow-inset,\n.ui-noboxshadow .ui-overlay-shadow,\n.ui-noboxshadow .ui-shadow-icon.ui-btn:after,\n.ui-noboxshadow .ui-shadow-icon .ui-btn:after,\n.ui-noboxshadow .ui-focus,\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow  input:focus,\n.ui-noboxshadow .ui-panel {\n\t-webkit-box-shadow: none !important;\n\t-moz-box-shadow: none !important;\n\tbox-shadow: none !important;\n}\n.ui-noboxshadow .ui-btn:focus,\n.ui-noboxshadow .ui-focus {\n\toutline-width: 1px;\n\toutline-style: auto;\n}\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/jquery.timeago.js",
    "content": "/**\n * Timeago is a jQuery plugin that makes it easy to support automatically\n * updating fuzzy timestamps (e.g. \"4 minutes ago\" or \"about 1 day ago\").\n *\n * @name timeago\n * @version 1.6.7\n * @requires jQuery >=1.5.0 <4.0\n * @author Ryan McGeary\n * @license MIT License - http://www.opensource.org/licenses/mit-license.php\n *\n * For usage and examples, visit:\n * http://timeago.yarp.com/\n *\n * Copyright (c) 2008-2019, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)\n */\n\n(function (factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define(['jquery'], factory);\n  } else if (typeof module === 'object' && typeof module.exports === 'object') {\n    factory(require('jquery'));\n  } else {\n    // Browser globals\n    factory(jQuery);\n  }\n}(function ($) {\n  $.timeago = function(timestamp) {\n    if (timestamp instanceof Date) {\n      return inWords(timestamp);\n    } else if (typeof timestamp === \"string\") {\n      return inWords($.timeago.parse(timestamp));\n    } else if (typeof timestamp === \"number\") {\n      return inWords(new Date(timestamp));\n    } else {\n      return inWords($.timeago.datetime(timestamp));\n    }\n  };\n  var $t = $.timeago;\n\n  $.extend($.timeago, {\n    settings: {\n      refreshMillis: 60000,\n      allowPast: true,\n      allowFuture: false,\n      localeTitle: false,\n      cutoff: 0,\n      autoDispose: true,\n      strings: {\n        prefixAgo: null,\n        prefixFromNow: null,\n        suffixAgo: \"ago\",\n        suffixFromNow: \"from now\",\n        inPast: 'any moment now',\n        seconds: \"less than a minute\",\n        minute: \"about a minute\",\n        minutes: \"%d minutes\",\n        hour: \"about an hour\",\n        hours: \"about %d hours\",\n        day: \"a day\",\n        days: \"%d days\",\n        month: \"about a month\",\n        months: \"%d months\",\n        year: \"about a year\",\n        years: \"%d years\",\n        wordSeparator: \" \",\n        numbers: []\n      }\n    },\n\n    inWords: function(distanceMillis) {\n      if (!this.settings.allowPast && ! this.settings.allowFuture) {\n          throw 'timeago allowPast and allowFuture settings can not both be set to false.';\n      }\n\n      var $l = this.settings.strings;\n      var prefix = $l.prefixAgo;\n      var suffix = $l.suffixAgo;\n      if (this.settings.allowFuture) {\n        if (distanceMillis < 0) {\n          prefix = $l.prefixFromNow;\n          suffix = $l.suffixFromNow;\n        }\n      }\n\n      if (!this.settings.allowPast && distanceMillis >= 0) {\n        return this.settings.strings.inPast;\n      }\n\n      var seconds = Math.abs(distanceMillis) / 1000;\n      var minutes = seconds / 60;\n      var hours = minutes / 60;\n      var days = hours / 24;\n      var years = days / 365;\n\n      function substitute(stringOrFunction, number) {\n        var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;\n        var value = ($l.numbers && $l.numbers[number]) || number;\n        return string.replace(/%d/i, value);\n      }\n\n      var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||\n        seconds < 90 && substitute($l.minute, 1) ||\n        minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||\n        minutes < 90 && substitute($l.hour, 1) ||\n        hours < 24 && substitute($l.hours, Math.round(hours)) ||\n        hours < 42 && substitute($l.day, 1) ||\n        days < 30 && substitute($l.days, Math.round(days)) ||\n        days < 45 && substitute($l.month, 1) ||\n        days < 365 && substitute($l.months, Math.round(days / 30)) ||\n        years < 1.5 && substitute($l.year, 1) ||\n        substitute($l.years, Math.round(years));\n\n      var separator = $l.wordSeparator || \"\";\n      if ($l.wordSeparator === undefined) { separator = \" \"; }\n      return $.trim([prefix, words, suffix].join(separator));\n    },\n\n    parse: function(iso8601) {\n      var s = $.trim(iso8601);\n      s = s.replace(/\\.\\d+/,\"\"); // remove milliseconds\n      s = s.replace(/-/,\"/\").replace(/-/,\"/\");\n      s = s.replace(/T/,\" \").replace(/Z/,\" UTC\");\n      s = s.replace(/([\\+\\-]\\d\\d)\\:?(\\d\\d)/,\" $1$2\"); // -04:00 -> -0400\n      s = s.replace(/([\\+\\-]\\d\\d)$/,\" $100\"); // +09 -> +0900\n      return new Date(s);\n    },\n    datetime: function(elem) {\n      var iso8601 = $t.isTime(elem) ? $(elem).attr(\"datetime\") : $(elem).attr(\"title\");\n      return $t.parse(iso8601);\n    },\n    isTime: function(elem) {\n      // jQuery's `is()` doesn't play well with HTML5 in IE\n      return $(elem).get(0).tagName.toLowerCase() === \"time\"; // $(elem).is(\"time\");\n    }\n  });\n\n  // functions that can be called via $(el).timeago('action')\n  // init is default when no action is given\n  // functions are called with context of a single element\n  var functions = {\n    init: function() {\n      functions.dispose.call(this);\n      var refresh_el = $.proxy(refresh, this);\n      refresh_el();\n      var $s = $t.settings;\n      if ($s.refreshMillis > 0) {\n        this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis);\n      }\n    },\n    update: function(timestamp) {\n      var date = (timestamp instanceof Date) ? timestamp : $t.parse(timestamp);\n      $(this).data('timeago', { datetime: date });\n      if ($t.settings.localeTitle) {\n        $(this).attr(\"title\", date.toLocaleString());\n      }\n      refresh.apply(this);\n    },\n    updateFromDOM: function() {\n      $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr(\"datetime\") : $(this).attr(\"title\") ) });\n      refresh.apply(this);\n    },\n    dispose: function () {\n      if (this._timeagoInterval) {\n        window.clearInterval(this._timeagoInterval);\n        this._timeagoInterval = null;\n      }\n    }\n  };\n\n  $.fn.timeago = function(action, options) {\n    var fn = action ? functions[action] : functions.init;\n    if (!fn) {\n      throw new Error(\"Unknown function name '\"+ action +\"' for timeago\");\n    }\n    // each over objects here and call the requested function\n    this.each(function() {\n      fn.call(this, options);\n    });\n    return this;\n  };\n\n  function refresh() {\n    var $s = $t.settings;\n\n    //check if it's still visible\n    if ($s.autoDispose && !$.contains(document.documentElement,this)) {\n      //stop if it has been removed\n      $(this).timeago(\"dispose\");\n      return this;\n    }\n\n    var data = prepareData(this);\n\n    if (!isNaN(data.datetime)) {\n      if ( $s.cutoff === 0 || Math.abs(distance(data.datetime)) < $s.cutoff) {\n        $(this).text(inWords(data.datetime));\n      } else {\n        if ($(this).attr('title').length > 0) {\n            $(this).text($(this).attr('title'));\n        }\n      }\n    }\n    return this;\n  }\n\n  function prepareData(element) {\n    element = $(element);\n    if (!element.data(\"timeago\")) {\n      element.data(\"timeago\", { datetime: $t.datetime(element) });\n      var text = $.trim(element.text());\n      if ($t.settings.localeTitle) {\n        element.attr(\"title\", element.data('timeago').datetime.toLocaleString());\n      } else if (text.length > 0 && !($t.isTime(element) && element.attr(\"title\"))) {\n        element.attr(\"title\", text);\n      }\n    }\n    return element.data(\"timeago\");\n  }\n\n  function inWords(date) {\n    return $t.inWords(distance(date));\n  }\n\n  function distance(date) {\n    return (new Date().getTime() - date.getTime());\n  }\n\n  // fix for IE6 suckage\n  document.createElement(\"abbr\");\n  document.createElement(\"time\");\n}));\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.BezierCurveRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    // Class: $.jqplot.BezierCurveRenderer.js\r\n    // Renderer which draws lines as stacked bezier curves.\r\n    // Data for the line will not be specified as an array of\r\n    // [x, y] data point values, but as a an array of [start piont, bezier curve]\r\n    // So, the line is specified as: [[xstart, ystart], [cp1x, cp1y, cp2x, cp2y, xend, yend]].\r\n    $.jqplot.BezierCurveRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.BezierCurveRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.BezierCurveRenderer.prototype.constructor = $.jqplot.BezierCurveRenderer;\r\n\r\n    \r\n    // Method: setGridData\r\n    // converts the user data values to grid coordinates and stores them\r\n    // in the gridData array.\r\n    // Called with scope of a series.\r\n    $.jqplot.BezierCurveRenderer.prototype.setGridData = function(plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        // this._plotData should be same as this.data\r\n        var data = this.data;\r\n        this.gridData = [];\r\n        this._prevGridData = [];\r\n        // if seriesIndex = 0, fill to x axis.\r\n        // if seriesIndex > 0, fill to previous series data.\r\n        var idx = this.index;\r\n        if (data.length == 2) {\r\n            if (idx == 0) {\r\n                this.gridData = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]),  \r\n                        xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])],\r\n                    [xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, this._yaxis.min)],\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)]\r\n                ];\r\n            }\r\n            else {\r\n                var psd = plot.series[idx-1].data;\r\n                this.gridData = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]),  \r\n                        xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])],\r\n                    [xp.call(this._xaxis, psd[1][4]), yp.call(this._yaxis, psd[1][5])],\r\n                    [xp.call(this._xaxis, psd[1][2]), yp.call(this._yaxis, psd[1][3]), \r\n                        xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]),  \r\n                        xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])]\r\n                ];\r\n            }\r\n        }\r\n        else {\r\n            if (idx == 0) {\r\n                this.gridData = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]),  \r\n                        xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])],\r\n                    [xp.call(this._xaxis, data[3][1]), yp.call(this._yaxis, this._yaxis.min)],\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)]\r\n                ];\r\n            }\r\n            else {\r\n                var psd = plot.series[idx-1].data;\r\n                this.gridData = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]),  \r\n                        xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])],\r\n                    [xp.call(this._xaxis, psd[3][0]), yp.call(this._yaxis, psd[3][1])],\r\n                    [xp.call(this._xaxis, psd[2][0]), yp.call(this._yaxis, psd[2][1]), \r\n                        xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]),  \r\n                        xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])]\r\n                ];\r\n            }\r\n        }\r\n    };\r\n    \r\n    // Method: makeGridData\r\n    // converts any arbitrary data values to grid coordinates and\r\n    // returns them.  This method exists so that plugins can use a series'\r\n    // linerenderer to generate grid data points without overwriting the\r\n    // grid data associated with that series.\r\n    // Called with scope of a series.\r\n    $.jqplot.BezierCurveRenderer.prototype.makeGridData = function(data, plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var gd = [];\r\n        var pgd = [];\r\n        // if seriesIndex = 0, fill to x axis.\r\n        // if seriesIndex > 0, fill to previous series data.\r\n        var idx = this.index;\r\n        if (data.length == 2) {\r\n            if (idx == 0) {\r\n                gd = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]),  \r\n                        xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])],\r\n                    [xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, this._yaxis.min)],\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)]\r\n                ];\r\n            }\r\n            else {\r\n                var psd = plot.series[idx-1].data;\r\n                gd = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[1][2]), yp.call(this._yaxis, data[1][3]),  \r\n                        xp.call(this._xaxis, data[1][4]), yp.call(this._yaxis, data[1][5])],\r\n                    [xp.call(this._xaxis, psd[1][4]), yp.call(this._yaxis, psd[1][5])],\r\n                    [xp.call(this._xaxis, psd[1][2]), yp.call(this._yaxis, psd[1][3]), \r\n                        xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]),  \r\n                        xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])]\r\n                ];\r\n            }\r\n        }\r\n        else {\r\n            if (idx == 0) {\r\n                gd = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]),  \r\n                        xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])],\r\n                    [xp.call(this._xaxis, data[3][1]), yp.call(this._yaxis, this._yaxis.min)],\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, this._yaxis.min)]\r\n                ];\r\n            }\r\n            else {\r\n                var psd = plot.series[idx-1].data;\r\n                gd = [\r\n                    [xp.call(this._xaxis, data[0][0]), yp.call(this._yaxis, data[0][1])], \r\n                    [xp.call(this._xaxis, data[1][0]), yp.call(this._yaxis, data[1][1]), \r\n                        xp.call(this._xaxis, data[2][0]), yp.call(this._yaxis, data[2][1]),  \r\n                        xp.call(this._xaxis, data[3][0]), yp.call(this._yaxis, data[3][1])],\r\n                    [xp.call(this._xaxis, psd[3][0]), yp.call(this._yaxis, psd[3][1])],\r\n                    [xp.call(this._xaxis, psd[2][0]), yp.call(this._yaxis, psd[2][1]), \r\n                        xp.call(this._xaxis, psd[1][0]), yp.call(this._yaxis, psd[1][1]),  \r\n                        xp.call(this._xaxis, psd[0][0]), yp.call(this._yaxis, psd[0][1])]\r\n                ];\r\n            }\r\n        }\r\n        return gd;\r\n    };\r\n    \r\n\r\n    // called within scope of series.\r\n    $.jqplot.BezierCurveRenderer.prototype.draw = function(ctx, gd, options) {\r\n        var i;\r\n        ctx.save();\r\n        if (gd.length) {\r\n            if (this.showLine) {\r\n                ctx.save();\r\n                var opts = (options != null) ? options : {};\r\n                ctx.fillStyle = opts.fillStyle || this.color;\r\n                ctx.beginPath();\r\n                ctx.moveTo(gd[0][0], gd[0][1]);\r\n                ctx.bezierCurveTo(gd[1][0], gd[1][1], gd[1][2], gd[1][3], gd[1][4], gd[1][5]);\r\n                ctx.lineTo(gd[2][0], gd[2][1]);\r\n                if (gd[3].length == 2) {\r\n                    ctx.lineTo(gd[3][0], gd[3][1]);\r\n                }\r\n                else {\r\n                    ctx.bezierCurveTo(gd[3][0], gd[3][1], gd[3][2], gd[3][3], gd[3][4], gd[3][5]);\r\n                }\r\n                ctx.closePath();\r\n                ctx.fill();\r\n                ctx.restore();\r\n            }\r\n        }\r\n        \r\n        ctx.restore();\r\n    };  \r\n    \r\n    $.jqplot.BezierCurveRenderer.prototype.drawShadow = function(ctx, gd, options) {\r\n        // This is a no-op, shadows drawn with lines.\r\n    };\r\n    \r\n    $.jqplot.BezierAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.BezierAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.BezierAxisRenderer.prototype.constructor = $.jqplot.BezierAxisRenderer;\r\n        \r\n    \r\n    // Axes on a plot with Bezier Curves\r\n    $.jqplot.BezierAxisRenderer.prototype.init = function(options){\r\n        $.extend(true, this, options);\r\n        var db = this._dataBounds;\r\n        // Go through all the series attached to this axis and find\r\n        // the min/max bounds for this axis.\r\n        for (var i=0; i<this._series.length; i++) {\r\n            var s = this._series[i];\r\n            var d = s.data;  \r\n            if (d.length == 4) {\r\n                for (var j=0; j<d.length; j++) { \r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        if (d[j][0] < db.min || db.min == null) {\r\n                            db.min = d[j][0];\r\n                        }\r\n                        if (d[j][0] > db.max || db.max == null) {\r\n                            db.max = d[j][0];\r\n                        }\r\n                    }              \r\n                    else {\r\n                        if (d[j][1] < db.min || db.min == null) {\r\n                            db.min = d[j][1];\r\n                        }\r\n                        if (d[j][1] > db.max || db.max == null) {\r\n                            db.max = d[j][1];\r\n                        }\r\n                    }              \r\n                }\r\n            }          \r\n            else {    \r\n                if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                    if (d[0][0] < db.min || db.min == null) {\r\n                        db.min = d[0][0];\r\n                    }\r\n                    if (d[0][0] > db.max || db.max == null) {\r\n                        db.max = d[0][0];\r\n                    }\r\n                    for (var j=0; j<5; j+=2) {\r\n                        if (d[1][j] < db.min || db.min == null) {\r\n                            db.min = d[1][j];\r\n                        }\r\n                        if (d[1][j] > db.max || db.max == null) {\r\n                            db.max = d[1][j];\r\n                        }\r\n                    }\r\n                }              \r\n                else {\r\n                    if (d[0][1] < db.min || db.min == null) {\r\n                        db.min = d[0][1];\r\n                    }\r\n                    if (d[0][1] > db.max || db.max == null) {\r\n                        db.max = d[0][1];\r\n                    }\r\n                    for (var j=1; j<6; j+=2) {\r\n                        if (d[1][j] < db.min || db.min == null) {\r\n                            db.min = d[1][j];\r\n                        }\r\n                        if (d[1][j] > db.max || db.max == null) {\r\n                            db.max = d[1][j];\r\n                        }\r\n                    }\r\n                }           \r\n            }\r\n        }\r\n    };\r\n    \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        options = options || {};\r\n        options.axesDefaults = $.extend(true, {pad:0}, options.axesDefaults);\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        options.legend = $.extend(true, {placement:'outside'}, options.legend);\r\n        // only set these if there is a pie series\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer == $.jqplot.BezierCurveRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer == $.jqplot.BezierCurveRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.BezierAxisRenderer;\r\n        }\r\n    }\r\n    \r\n    $.jqplot.preInitHooks.push(preInit);\r\n    \r\n})(jQuery);    "
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.barRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    \r\n    // Class: $.jqplot.BarRenderer\r\n    // A plugin renderer for jqPlot to draw a bar plot.\r\n    // Draws series as a line.\r\n    \r\n    $.jqplot.BarRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.BarRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.BarRenderer.prototype.constructor = $.jqplot.BarRenderer;\r\n    \r\n    // called with scope of series.\r\n    $.jqplot.BarRenderer.prototype.init = function(options, plot) {\r\n        // Group: Properties\r\n        //\r\n        // prop: barPadding\r\n        // Number of pixels between adjacent bars at the same axis value.\r\n        this.barPadding = 8;\r\n        // prop: barMargin\r\n        // Number of pixels between groups of bars at adjacent axis values.\r\n        this.barMargin = 10;\r\n        // prop: barDirection\r\n        // 'vertical' = up and down bars, 'horizontal' = side to side bars\r\n        this.barDirection = 'vertical';\r\n        // prop: barWidth\r\n        // Width of the bar in pixels (auto by devaul).  null = calculated automatically.\r\n        this.barWidth = null;\r\n        // prop: shadowOffset\r\n        // offset of the shadow from the slice and offset of \r\n        // each succesive stroke of the shadow from the last.\r\n        this.shadowOffset = 2;\r\n        // prop: shadowDepth\r\n        // number of strokes to apply to the shadow, \r\n        // each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 5;\r\n        // prop: shadowAlpha\r\n        // transparency of the shadow (0 = transparent, 1 = opaque)\r\n        this.shadowAlpha = 0.08;\r\n        // prop: waterfall\r\n        // true to enable waterfall plot.\r\n        this.waterfall = false;\r\n        // prop: groups\r\n        // group bars into this many groups\r\n        this.groups = 1;\r\n        // prop: varyBarColor\r\n        // true to color each bar of a series separately rather than\r\n        // have every bar of a given series the same color.\r\n        // If used for non-stacked multiple series bar plots, user should\r\n        // specify a separate 'seriesColors' array for each series.\r\n        // Otherwise, each series will set their bars to the same color array.\r\n        // This option has no Effect for stacked bar charts and is disabled.\r\n        this.varyBarColor = false;\r\n        // prop: highlightMouseOver\r\n        // True to highlight slice when moused over.\r\n        // This must be false to enable highlightMouseDown to highlight when clicking on a slice.\r\n        this.highlightMouseOver = true;\r\n        // prop: highlightMouseDown\r\n        // True to highlight when a mouse button is pressed over a slice.\r\n        // This will be disabled if highlightMouseOver is true.\r\n        this.highlightMouseDown = false;\r\n        // prop: highlightColors\r\n        // an array of colors to use when highlighting a bar.\r\n        this.highlightColors = [];\r\n        // prop: transposedData\r\n        // NOT IMPLEMENTED YET.  True if this is a horizontal bar plot and \r\n        // x and y values are \"transposed\".  Tranposed, or \"swapped\", data is \r\n        // required prior to rev. 894 builds of jqPlot with horizontal bars. \r\n        // Allows backward compatability of bar renderer horizontal bars with \r\n        // old style data sets.\r\n        this.transposedData = true;\r\n        this.renderer.animation = {\r\n            show: false,\r\n            direction: 'down',\r\n            speed: 3000,\r\n            _supported: true\r\n        };\r\n        this._type = 'bar';\r\n        \r\n        // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver\r\n        if (options.highlightMouseDown && options.highlightMouseOver == null) {\r\n            options.highlightMouseOver = false;\r\n        }\r\n        \r\n        //////\r\n        // This is probably wrong here.\r\n        // After going back and forth on whether renderer should be the thing\r\n        // or extend the thing, it seems that it it best if it is a property\r\n        // on the thing.  This should be something that is commonized \r\n        // among series renderers in the future.\r\n        //////\r\n        $.extend(true, this, options);\r\n\r\n        // really should probably do this\r\n        $.extend(true, this.renderer, options);\r\n        // fill is still needed to properly draw the legend.\r\n        // bars have to be filled.\r\n        this.fill = true;\r\n\r\n        // if horizontal bar and animating, reset the default direction\r\n        if (this.barDirection === 'horizontal' && this.rendererOptions.animation && this.rendererOptions.animation.direction == null) {\r\n            this.renderer.animation.direction = 'left';\r\n        }\r\n        \r\n        if (this.waterfall) {\r\n            this.fillToZero = false;\r\n            this.disableStack = true;\r\n        }\r\n        \r\n        if (this.barDirection == 'vertical' ) {\r\n            this._primaryAxis = '_xaxis';\r\n            this._stackAxis = 'y';\r\n            this.fillAxis = 'y';\r\n        }\r\n        else {\r\n            this._primaryAxis = '_yaxis';\r\n            this._stackAxis = 'x';\r\n            this.fillAxis = 'x';\r\n        }\r\n        // index of the currenty highlighted point, if any\r\n        this._highlightedPoint = null;\r\n        // total number of values for all bar series, total number of bar series, and position of this series\r\n        this._plotSeriesInfo = null;\r\n        // Array of actual data colors used for each data point.\r\n        this._dataColors = [];\r\n        this._barPoints = [];\r\n        \r\n        // set the shape renderer options\r\n        var opts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, strokeStyle:this.color, fillStyle:this.color, closePath:this.fill};\r\n        this.renderer.shapeRenderer.init(opts);\r\n        // set the shadow renderer options\r\n        var sopts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, closePath:this.fill};\r\n        this.renderer.shadowRenderer.init(sopts);\r\n        \r\n        plot.postInitHooks.addOnce(postInit);\r\n        plot.postDrawHooks.addOnce(postPlotDraw);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);\r\n        plot.eventListenerHooks.addOnce('jqplotClick', handleClick);\r\n        plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); \r\n    };\r\n    \r\n    // called with scope of series\r\n    function barPreInit(target, data, seriesDefaults, options) {\r\n        if (this.rendererOptions.barDirection == 'horizontal') {\r\n            this._stackAxis = 'x';\r\n            this._primaryAxis = '_yaxis';\r\n        }\r\n        if (this.rendererOptions.waterfall == true) {\r\n            this._data = $.extend(true, [], this.data);\r\n            var sum = 0;\r\n            var pos = (!this.rendererOptions.barDirection || this.rendererOptions.barDirection === 'vertical' || this.transposedData === false) ? 1 : 0;\r\n            for(var i=0; i<this.data.length; i++) {\r\n                sum += this.data[i][pos];\r\n                if (i>0) {\r\n                    this.data[i][pos] += this.data[i-1][pos];\r\n                }\r\n            }\r\n            this.data[this.data.length] = (pos == 1) ? [this.data.length+1, sum] : [sum, this.data.length+1];\r\n            this._data[this._data.length] = (pos == 1) ? [this._data.length+1, sum] : [sum, this._data.length+1];\r\n        }\r\n        if (this.rendererOptions.groups > 1) {\r\n            this.breakOnNull = true;\r\n            var l = this.data.length;\r\n            var skip = parseInt(l/this.rendererOptions.groups, 10);\r\n            var count = 0;\r\n            for (var i=skip; i<l; i+=skip) {\r\n                this.data.splice(i+count, 0, [null, null]);\r\n                this._plotData.splice(i+count, 0, [null, null]);\r\n                this._stackData.splice(i+count, 0, [null, null]);\r\n                count++;\r\n            }\r\n            for (i=0; i<this.data.length; i++) {\r\n                if (this._primaryAxis == '_xaxis') {\r\n                    this.data[i][0] = i+1;\r\n                    this._plotData[i][0] = i+1;\r\n                    this._stackData[i][0] = i+1;\r\n                }\r\n                else {\r\n                    this.data[i][1] = i+1;\r\n                    this._plotData[i][1] = i+1;\r\n                    this._stackData[i][1] = i+1;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    \r\n    $.jqplot.preSeriesInitHooks.push(barPreInit);\r\n    \r\n    // needs to be called with scope of series, not renderer.\r\n    $.jqplot.BarRenderer.prototype.calcSeriesNumbers = function() {\r\n        var nvals = 0;\r\n        var nseries = 0;\r\n        var paxis = this[this._primaryAxis];\r\n        var s, series, pos;\r\n        // loop through all series on this axis\r\n        for (var i=0; i < paxis._series.length; i++) {\r\n            series = paxis._series[i];\r\n            if (series === this) {\r\n                pos = i;\r\n            }\r\n            // is the series rendered as a bar?\r\n            if (series.renderer.constructor == $.jqplot.BarRenderer) {\r\n                // gridData may not be computed yet, use data length insted\r\n                nvals += series.data.length;\r\n                nseries += 1;\r\n            }\r\n        }\r\n        // return total number of values for all bar series, total number of bar series, and position of this series\r\n        return [nvals, nseries, pos];\r\n    };\r\n\r\n    $.jqplot.BarRenderer.prototype.setBarWidth = function() {\r\n        // need to know how many data values we have on the approprate axis and figure it out.\r\n        var i;\r\n        var nvals = 0;\r\n        var nseries = 0;\r\n        var paxis = this[this._primaryAxis];\r\n        var s, series, pos;\r\n        var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);\r\n        nvals = temp[0];\r\n        nseries = temp[1];\r\n        var nticks = paxis.numberTicks;\r\n        var nbins = (nticks-1)/2;\r\n        // so, now we have total number of axis values.\r\n        if (paxis.name == 'xaxis' || paxis.name == 'x2axis') {\r\n            if (this._stack) {\r\n                this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals * nseries - this.barMargin;\r\n            }\r\n            else {\r\n                this.barWidth = ((paxis._offsets.max - paxis._offsets.min)/nbins  - this.barPadding * (nseries-1) - this.barMargin*2)/nseries;\r\n                // this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals - this.barPadding - this.barMargin/nseries;\r\n            }\r\n        }\r\n        else {\r\n            if (this._stack) {\r\n                this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals * nseries - this.barMargin;\r\n            }\r\n            else {\r\n                this.barWidth = ((paxis._offsets.min - paxis._offsets.max)/nbins  - this.barPadding * (nseries-1) - this.barMargin*2)/nseries;\r\n                // this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals - this.barPadding - this.barMargin/nseries;\r\n            }\r\n        }\r\n        return [nvals, nseries];\r\n    };\r\n\r\n    function computeHighlightColors (colors) {\r\n        var ret = [];\r\n        for (var i=0; i<colors.length; i++){\r\n            var rgba = $.jqplot.getColorComponents(colors[i]);\r\n            var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n            var sum = newrgb[0] + newrgb[1] + newrgb[2];\r\n            for (var j=0; j<3; j++) {\r\n                // when darkening, lowest color component can be is 60.\r\n                newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);\r\n                newrgb[j] = parseInt(newrgb[j], 10);\r\n            }\r\n            ret.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');\r\n        }\r\n        return ret;\r\n    }\r\n\r\n    function getStart(sidx, didx, comp, plot, axis) {\r\n        // check if sign change\r\n        var seriesIndex = sidx,\r\n            prevSeriesIndex = sidx - 1,\r\n            start,\r\n            prevVal,\r\n            aidx = (axis === 'x') ? 0 : 1;\r\n\r\n        // is this not the first series?\r\n        if (seriesIndex > 0) {\r\n            prevVal = plot.series[prevSeriesIndex]._plotData[didx][aidx];\r\n\r\n            // is there a sign change\r\n            if ((comp * prevVal) < 0) {\r\n                start = getStart(prevSeriesIndex, didx, comp, plot, axis);\r\n            }\r\n\r\n            // no sign change.\r\n            else {\r\n                start = plot.series[prevSeriesIndex].gridData[didx][aidx];\r\n            }\r\n\r\n        }\r\n\r\n        // if first series, return value at 0\r\n        else {\r\n\r\n            start = (aidx === 0) ? plot.series[seriesIndex]._xaxis.series_u2p(0) : plot.series[seriesIndex]._yaxis.series_u2p(0);\r\n        }\r\n\r\n        return start;\r\n    }\r\n\r\n    \r\n    $.jqplot.BarRenderer.prototype.draw = function(ctx, gridData, options, plot) {\r\n        var i;\r\n        // Ughhh, have to make a copy of options b/c it may be modified later.\r\n        var opts = $.extend({}, options);\r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        var xaxis = this.xaxis;\r\n        var yaxis = this.yaxis;\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var pointx, pointy;\r\n        // clear out data colors.\r\n        this._dataColors = [];\r\n        this._barPoints = [];\r\n        \r\n        if (this.barWidth == null || this.rendererOptions.barWidth == null) {//check pull request https://bitbucket.org/cleonello/jqplot/pull-request/61/fix-for-issue-513/diff\r\n            this.renderer.setBarWidth.call(this);\r\n        }\r\n        \r\n        var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);\r\n        var nvals = temp[0];\r\n        var nseries = temp[1];\r\n        var pos = temp[2];\r\n        var points = [];\r\n        \r\n        if (this._stack) {\r\n            this._barNudge = 0;\r\n        }\r\n        else {\r\n            this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding);\r\n        }\r\n        if (showLine) {\r\n            var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors);\r\n            var positiveColors = new $.jqplot.ColorGenerator(this.seriesColors);\r\n            var negativeColor = negativeColors.get(this.index);\r\n            if (! this.useNegativeColors) {\r\n                negativeColor = opts.fillStyle;\r\n            }\r\n            var positiveColor = opts.fillStyle;\r\n            var base;\r\n            var xstart; \r\n            var ystart;\r\n            \r\n            if (this.barDirection == 'vertical') {\r\n                for (var i=0; i<gridData.length; i++) {\r\n                    if (!this._stack && this.data[i][1] == null) {\r\n                        continue;\r\n                    }\r\n                    points = [];\r\n                    base = gridData[i][0] + this._barNudge;\r\n                    \r\n                    // stacked\r\n                    if (this._stack && this._prevGridData.length) {\r\n                        ystart = getStart(this.index, i, this._plotData[i][1], plot, 'y');\r\n                    }\r\n\r\n                    // not stacked\r\n                    else {\r\n                        if (this.fillToZero) {\r\n                            ystart = this._yaxis.series_u2p(0);\r\n                        }\r\n                        else if (this.waterfall && i > 0 && i < this.gridData.length-1) {\r\n                            ystart = this.gridData[i-1][1];\r\n                        }\r\n                        else if (this.waterfall && i == 0 && i < this.gridData.length-1) {\r\n                            if (this._yaxis.min <= 0 && this._yaxis.max >= 0) {\r\n                                ystart = this._yaxis.series_u2p(0);\r\n                            }\r\n                            else if (this._yaxis.min > 0) {\r\n                                ystart = ctx.canvas.height;\r\n                            }\r\n                            else {\r\n                                ystart = 0;\r\n                            }\r\n                        }\r\n                        else if (this.waterfall && i == this.gridData.length - 1) {\r\n                            if (this._yaxis.min <= 0 && this._yaxis.max >= 0) {\r\n                                ystart = this._yaxis.series_u2p(0);\r\n                            }\r\n                            else if (this._yaxis.min > 0) {\r\n                                ystart = ctx.canvas.height;\r\n                            }\r\n                            else {\r\n                                ystart = 0;\r\n                            }\r\n                        }\r\n                        else {\r\n                            ystart = ctx.canvas.height;\r\n                        }\r\n                    }\r\n                    if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) {\r\n                        if (this.varyBarColor && !this._stack) {\r\n                            if (this.useNegativeColors) {\r\n                                opts.fillStyle = negativeColors.next();\r\n                            }\r\n                            else {\r\n                                opts.fillStyle = positiveColors.next();\r\n                            }\r\n                        }\r\n                        else {\r\n                            opts.fillStyle = negativeColor;\r\n                        }\r\n                    }\r\n                    else {\r\n                        if (this.varyBarColor && !this._stack) {\r\n                            opts.fillStyle = positiveColors.next();\r\n                        }\r\n                        else {\r\n                            opts.fillStyle = positiveColor;\r\n                        }\r\n                    }\r\n                    \r\n                    if (!this.fillToZero || this._plotData[i][1] >= 0) { \r\n                        points.push([base-this.barWidth/2, ystart]);\r\n                        points.push([base-this.barWidth/2, gridData[i][1]]);\r\n                        points.push([base+this.barWidth/2, gridData[i][1]]);\r\n                        points.push([base+this.barWidth/2, ystart]);\r\n                    }\r\n                    // for negative bars make sure points are always ordered clockwise\r\n                    else {              \r\n                        points.push([base-this.barWidth/2, gridData[i][1]]);\r\n                        points.push([base-this.barWidth/2, ystart]);\r\n                        points.push([base+this.barWidth/2, ystart]);\r\n                        points.push([base+this.barWidth/2, gridData[i][1]]);\r\n                    }\r\n                    this._barPoints.push(points);\r\n                    // now draw the shadows if not stacked.\r\n                    // for stacked plots, they are predrawn by drawShadow\r\n                    if (shadow && !this._stack) {\r\n                        var sopts = $.extend(true, {}, opts);\r\n                        // need to get rid of fillStyle on shadow.\r\n                        delete sopts.fillStyle;\r\n                        this.renderer.shadowRenderer.draw(ctx, points, sopts);\r\n                    }\r\n                    var clr = opts.fillStyle || this.color;\r\n                    this._dataColors.push(clr);\r\n                    this.renderer.shapeRenderer.draw(ctx, points, opts); \r\n                }\r\n            }\r\n            \r\n            else if (this.barDirection == 'horizontal'){\r\n                for (var i=0; i<gridData.length; i++) {\r\n                    if (!this._stack && this.data[i][0] == null) {\r\n                        continue;\r\n                    }\r\n                    points = [];\r\n                    base = gridData[i][1] - this._barNudge;\r\n                    xstart;\r\n                    \r\n                    if (this._stack && this._prevGridData.length) {\r\n                        xstart = getStart(this.index, i, this._plotData[i][0], plot, 'x');\r\n                    }\r\n                    // not stacked\r\n                    else {\r\n                        if (this.fillToZero) {\r\n                            xstart = this._xaxis.series_u2p(0);\r\n                        }\r\n                        else if (this.waterfall && i > 0 && i < this.gridData.length-1) {\r\n                            xstart = this.gridData[i-1][0];\r\n                        }\r\n                        else if (this.waterfall && i == 0 && i < this.gridData.length-1) {\r\n                            if (this._xaxis.min <= 0 && this._xaxis.max >= 0) {\r\n                                xstart = this._xaxis.series_u2p(0);\r\n                            }\r\n                            else if (this._xaxis.min > 0) {\r\n                                xstart = 0;\r\n                            }\r\n                            else {\r\n                                xstart = 0;\r\n                            }\r\n                        }\r\n                        else if (this.waterfall && i == this.gridData.length - 1) {\r\n                            if (this._xaxis.min <= 0 && this._xaxis.max >= 0) {\r\n                                xstart = this._xaxis.series_u2p(0);\r\n                            }\r\n                            else if (this._xaxis.min > 0) {\r\n                                xstart = 0;\r\n                            }\r\n                            else {\r\n                                xstart = ctx.canvas.width;\r\n                            }\r\n                        }\r\n                        else {\r\n                            xstart = 0;\r\n                        }\r\n                    }\r\n                    if ((this.fillToZero && this._plotData[i][0] < 0) || (this.waterfall && this._data[i][0] < 0)) {\r\n                        if (this.varyBarColor && !this._stack) {\r\n                            if (this.useNegativeColors) {\r\n                                opts.fillStyle = negativeColors.next();\r\n                            }\r\n                            else {\r\n                                opts.fillStyle = positiveColors.next();\r\n                            }\r\n                        }\r\n                        else {\r\n                            opts.fillStyle = negativeColor;\r\n                        }\r\n                    }\r\n                    else {\r\n                        if (this.varyBarColor && !this._stack) {\r\n                            opts.fillStyle = positiveColors.next();\r\n                        }\r\n                        else {\r\n                            opts.fillStyle = positiveColor;\r\n                        }                    \r\n                    }\r\n                    \r\n\r\n                    if (!this.fillToZero || this._plotData[i][0] >= 0) {\r\n                        points.push([xstart, base + this.barWidth / 2]);\r\n                        points.push([xstart, base - this.barWidth / 2]);\r\n                        points.push([gridData[i][0], base - this.barWidth / 2]);\r\n                        points.push([gridData[i][0], base + this.barWidth / 2]);\r\n                    }\r\n                    else {\r\n                        points.push([gridData[i][0], base + this.barWidth / 2]);\r\n                        points.push([gridData[i][0], base - this.barWidth / 2]);\r\n                        points.push([xstart, base - this.barWidth / 2]);\r\n                        points.push([xstart, base + this.barWidth / 2]);\r\n                    }\r\n\r\n                    this._barPoints.push(points);\r\n                    // now draw the shadows if not stacked.\r\n                    // for stacked plots, they are predrawn by drawShadow\r\n                    if (shadow && !this._stack) {\r\n                        var sopts = $.extend(true, {}, opts);\r\n                        delete sopts.fillStyle;\r\n                        this.renderer.shadowRenderer.draw(ctx, points, sopts);\r\n                    }\r\n                    var clr = opts.fillStyle || this.color;\r\n                    this._dataColors.push(clr);\r\n                    this.renderer.shapeRenderer.draw(ctx, points, opts);\r\n                } \r\n            }\r\n        }                \r\n        \r\n        if (this.highlightColors.length == 0) {\r\n            this.highlightColors = $.jqplot.computeHighlightColors(this._dataColors);\r\n        }\r\n        \r\n        else if (typeof(this.highlightColors) == 'string') {\r\n            var temp = this.highlightColors;\r\n            this.highlightColors = [];\r\n            for (var i=0; i<this._dataColors.length; i++) {\r\n                this.highlightColors.push(temp);\r\n            }\r\n        }\r\n        \r\n    };\r\n    \r\n     \r\n    // for stacked plots, shadows will be pre drawn by drawShadow.\r\n    $.jqplot.BarRenderer.prototype.drawShadow = function(ctx, gridData, options, plot) {\r\n        var i;\r\n        var opts = (options != undefined) ? options : {};\r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        var xaxis = this.xaxis;\r\n        var yaxis = this.yaxis;\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var pointx, points, pointy, nvals, nseries, pos;\r\n        \r\n        if (this._stack && this.shadow) {\r\n            if (this.barWidth == null) {\r\n                this.renderer.setBarWidth.call(this);\r\n            }\r\n        \r\n            var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);\r\n            nvals = temp[0];\r\n            nseries = temp[1];\r\n            pos = temp[2];\r\n        \r\n            if (this._stack) {\r\n                this._barNudge = 0;\r\n            }\r\n            else {\r\n                this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding);\r\n            }\r\n            if (showLine) {\r\n            \r\n                if (this.barDirection == 'vertical') {\r\n                    for (var i=0; i<gridData.length; i++) {\r\n                        if (this.data[i][1] == null) {\r\n                            continue;\r\n                        }\r\n                        points = [];\r\n                        var base = gridData[i][0] + this._barNudge;\r\n                        var ystart;\r\n                    \r\n                        if (this._stack && this._prevGridData.length) {\r\n                            ystart = getStart(this.index, i, this._plotData[i][1], plot, 'y');\r\n                        }\r\n                        else {\r\n                            if (this.fillToZero) {\r\n                                ystart = this._yaxis.series_u2p(0);\r\n                            }\r\n                            else {\r\n                                ystart = ctx.canvas.height;\r\n                            }\r\n                        }\r\n                    \r\n                        points.push([base-this.barWidth/2, ystart]);\r\n                        points.push([base-this.barWidth/2, gridData[i][1]]);\r\n                        points.push([base+this.barWidth/2, gridData[i][1]]);\r\n                        points.push([base+this.barWidth/2, ystart]);\r\n                        this.renderer.shadowRenderer.draw(ctx, points, opts);\r\n                    }\r\n                }\r\n            \r\n                else if (this.barDirection == 'horizontal'){\r\n                    for (var i=0; i<gridData.length; i++) {\r\n                        if (this.data[i][0] == null) {\r\n                            continue;\r\n                        }\r\n                        points = [];\r\n                        var base = gridData[i][1] - this._barNudge;\r\n                        var xstart;\r\n                    \r\n                        if (this._stack && this._prevGridData.length) {\r\n                            xstart = getStart(this.index, i, this._plotData[i][0], plot, 'x');\r\n                        }\r\n                        else {\r\n                            if (this.fillToZero) {\r\n                                xstart = this._xaxis.series_u2p(0);\r\n                            }\r\n                            else {\r\n                                xstart = 0;\r\n                            }\r\n                        }\r\n                    \r\n                        points.push([xstart, base+this.barWidth/2]);\r\n                        points.push([gridData[i][0], base+this.barWidth/2]);\r\n                        points.push([gridData[i][0], base-this.barWidth/2]);\r\n                        points.push([xstart, base-this.barWidth/2]);\r\n                        this.renderer.shadowRenderer.draw(ctx, points, opts);\r\n                    }  \r\n                }\r\n            }   \r\n            \r\n        }\r\n    };\r\n    \r\n    function postInit(target, data, options) {\r\n        for (var i=0; i<this.series.length; i++) {\r\n            if (this.series[i].renderer.constructor == $.jqplot.BarRenderer) {\r\n                // don't allow mouseover and mousedown at same time.\r\n                if (this.series[i].highlightMouseOver) {\r\n                    this.series[i].highlightMouseDown = false;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    function postPlotDraw() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.barRenderer && this.plugins.barRenderer.highlightCanvas) {\r\n\r\n            this.plugins.barRenderer.highlightCanvas.resetCanvas();\r\n            this.plugins.barRenderer.highlightCanvas = null;\r\n        }\r\n         \r\n        this.plugins.barRenderer = {highlightedSeriesIndex:null};\r\n        this.plugins.barRenderer.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        \r\n        this.eventCanvas._elem.before(this.plugins.barRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-barRenderer-highlight-canvas', this._plotDimensions, this));\r\n        this.plugins.barRenderer.highlightCanvas.setContext();\r\n        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });\r\n    }   \r\n    \r\n    function highlight (plot, sidx, pidx, points) {\r\n        var s = plot.series[sidx];\r\n        var canvas = plot.plugins.barRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        s._highlightedPoint = pidx;\r\n        plot.plugins.barRenderer.highlightedSeriesIndex = sidx;\r\n        var opts = {fillStyle: s.highlightColors[pidx]};\r\n        s.renderer.shapeRenderer.draw(canvas._ctx, points, opts);\r\n        canvas = null;\r\n    }\r\n    \r\n    function unhighlight (plot) {\r\n        var canvas = plot.plugins.barRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            plot.series[i]._highlightedPoint = null;\r\n        }\r\n        plot.plugins.barRenderer.highlightedSeriesIndex = null;\r\n        plot.target.trigger('jqplotDataUnhighlight');\r\n        canvas =  null;\r\n    }\r\n    \r\n    \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt1 = jQuery.Event('jqplotDataMouseOver');\r\n            evt1.pageX = ev.pageX;\r\n            evt1.pageY = ev.pageY;\r\n            plot.target.trigger(evt1, ins);\r\n            if (plot.series[ins[0]].show && plot.series[ins[0]].highlightMouseOver &&\r\n                !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {\r\n        var idx = plot.plugins.barRenderer.highlightedSeriesIndex;\r\n        if (idx != null && plot.series[idx].highlightMouseDown) {\r\n            unhighlight(plot);\r\n        }\r\n    }\r\n    \r\n    function handleClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt = jQuery.Event('jqplotDataClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var idx = plot.plugins.barRenderer.highlightedSeriesIndex;\r\n            if (idx != null && plot.series[idx].highlightMouseDown) {\r\n                unhighlight(plot);\r\n            }\r\n            var evt = jQuery.Event('jqplotDataRightClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    \r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.blockRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.BlockRenderer\r\n     * Plugin renderer to draw a x-y block chart.  A Block chart has data points displayed as\r\n     * colored squares with a text label inside.  Data must be supplied in the form:\r\n     * \r\n     * > [[x1, y1, \"label 1\", {css}], [x2, y2, \"label 2\", {css}], ...]\r\n     * \r\n     * The label and css object are optional.  If the label is ommitted, the\r\n     * box will collapse unless a css height and/or width is specified.\r\n     * \r\n     * The css object is an object specifying css properties \r\n     * such as:\r\n     * \r\n     * > {background:'#4f98a5', border:'3px solid gray', padding:'1px'}\r\n     * \r\n     * Note that css properties specified with the data point override defaults\r\n     * specified with the series.\r\n     * \r\n     */\r\n    $.jqplot.BlockRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.BlockRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.BlockRenderer.prototype.constructor = $.jqplot.BlockRenderer;\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.BlockRenderer.prototype.init = function(options) {\r\n        // Group: Properties\r\n        //\r\n        // prop: css\r\n        // default css styles that will be applied to all data blocks.\r\n        // these values will be overridden by css styles supplied with the\r\n        // individulal data points.\r\n        this.css = {padding:'2px', border:'1px solid #999', textAlign:'center'};\r\n        // prop: escapeHtml\r\n        // true to escape html in the box label.\r\n        this.escapeHtml = false;\r\n        // prop: insertBreaks\r\n        // true to turn spaces in data block label into html breaks <br />.\r\n        this.insertBreaks = true;\r\n        // prop: varyBlockColors\r\n        // true to vary the color of each block in this series according to\r\n        // the seriesColors array.  False to set each block to the color\r\n        // specified on this series.  This has no effect if a css background color\r\n        // option is specified in the renderer css options.\r\n        this.varyBlockColors = false;\r\n        $.extend(true, this, options);\r\n        if (this.css.backgroundColor) {\r\n            this.color = this.css.backgroundColor;\r\n        }\r\n        else if (this.css.background) {\r\n            this.color = this.css.background;\r\n        }\r\n        else if (!this.varyBlockColors) {\r\n            this.css.background = this.color;\r\n        }\r\n        this.canvas = new $.jqplot.BlockCanvas();\r\n        this.shadowCanvas =  new $.jqplot.BlockCanvas();\r\n        this.canvas._plotDimensions = this._plotDimensions;\r\n        this.shadowCanvas._plotDimensions = this._plotDimensions;\r\n        this._type = 'block';\r\n        \r\n        // group: Methods \r\n        //\r\n        // Method: moveBlock\r\n        // Moves an individual block.  More efficient than redrawing\r\n        // the whole series by calling plot.drawSeries().\r\n        // Properties:\r\n        // idx - the 0 based index of the block or point in this series.\r\n        // x - the x coordinate in data units (value on x axis) to move the block to.\r\n        // y - the y coordinate in data units (value on the y axis) to move the block to.\r\n        // duration - optional parameter to create an animated movement.  Can be a\r\n        // number (higher is slower animation) or 'fast', 'normal' or 'slow'.  If not\r\n        // provided, the element is moved without any animation.\r\n        this.moveBlock = function (idx, x, y, duration) {\r\n            // update plotData, stackData, data and gridData\r\n            // x and y are in data coordinates.\r\n            var el = this.canvas._elem.children(':eq('+idx+')');\r\n            this.data[idx][0] = x;\r\n            this.data[idx][1] = y;\r\n            this._plotData[idx][0] = x;\r\n            this._plotData[idx][1] = y;\r\n            this._stackData[idx][0] = x;\r\n            this._stackData[idx][1] = y;\r\n            this.gridData[idx][0] = this._xaxis.series_u2p(x);\r\n            this.gridData[idx][1] = this._yaxis.series_u2p(y);\r\n            var w = el.outerWidth();\r\n            var h = el.outerHeight();\r\n            var left = this.gridData[idx][0] - w/2 + 'px';\r\n            var top = this.gridData[idx][1] - h/2 + 'px';\r\n            if (duration) {\r\n                if (parseInt(duration, 10)) {\r\n                    duration = parseInt(duration, 10);\r\n                }\r\n                el.animate({left:left, top:top}, duration);\r\n            }\r\n            else {\r\n                el.css({left:left, top:top});\r\n            }\r\n            el = null;\r\n        };\r\n    };\r\n    \r\n    // called with scope of series\r\n    $.jqplot.BlockRenderer.prototype.draw = function (ctx, gd, options) {\r\n        if (this.plugins.pointLabels) {\r\n            this.plugins.pointLabels.show = false;\r\n        }\r\n        var i, el, d, gd, t, css, w, h, left, top;\r\n        var opts = (options != undefined) ? options : {};\r\n        var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);\r\n        this.canvas._elem.empty();\r\n        for (i=0; i<this.gridData.length; i++) {\r\n            d = this.data[i];\r\n            gd = this.gridData[i];\r\n            t = '';\r\n            css = {};\r\n            if (typeof d[2] == 'string') {\r\n                t = d[2];\r\n            }\r\n            else if (typeof d[2] == 'object') {\r\n                css = d[2];\r\n            }\r\n            if (typeof d[3] ==  'object') {\r\n                css = d[3];\r\n            }\r\n            if (this.insertBreaks){ \r\n                t = t.replace(/ /g, '<br />');\r\n            }\r\n            css = $.extend(true, {}, this.css, css);\r\n            // create a div\r\n            el = $('<div style=\"position:absolute;margin-left:auto;margin-right:auto;\"></div>');\r\n            this.canvas._elem.append(el);\r\n            // set text\r\n            this.escapeHtml ? el.text(t) : el.html(t);\r\n            // style it\r\n            // remove styles we don't want overridden.\r\n            delete css.position;\r\n            delete css.marginRight;\r\n            delete css.marginLeft;\r\n            if (!css.background && !css.backgroundColor && !css.backgroundImage){ \r\n                css.background = colorGenerator.next();\r\n            }\r\n            el.css(css);\r\n            w = el.outerWidth();\r\n            h = el.outerHeight();\r\n            left = gd[0] - w/2 + 'px';\r\n            top = gd[1] - h/2 + 'px';\r\n            el.css({left:left, top:top});\r\n            el = null;\r\n        }\r\n    };\r\n    \r\n    $.jqplot.BlockCanvas = function() {\r\n        $.jqplot.ElemContainer.call(this);\r\n        this._ctx;  \r\n    };\r\n    \r\n    $.jqplot.BlockCanvas.prototype = new $.jqplot.ElemContainer();\r\n    $.jqplot.BlockCanvas.prototype.constructor = $.jqplot.BlockCanvas;\r\n    \r\n    $.jqplot.BlockCanvas.prototype.createElement = function(offsets, clss, plotDimensions) {\r\n        this._offsets = offsets;\r\n        var klass = 'jqplot-blockCanvas';\r\n        if (clss != undefined) {\r\n            klass = clss;\r\n        }\r\n        var elem;\r\n        // if this canvas already has a dom element, don't make a new one.\r\n        if (this._elem) {\r\n            elem = this._elem.get(0);\r\n        }\r\n        else {\r\n            elem = document.createElement('div');\r\n        }\r\n        // if new plotDimensions supplied, use them.\r\n        if (plotDimensions != undefined) {\r\n            this._plotDimensions = plotDimensions;\r\n        }\r\n        \r\n        var w = this._plotDimensions.width - this._offsets.left - this._offsets.right + 'px';\r\n        var h = this._plotDimensions.height - this._offsets.top - this._offsets.bottom + 'px';\r\n        this._elem = $(elem);\r\n        this._elem.css({ position: 'absolute', width:w, height:h, left: this._offsets.left, top: this._offsets.top });\r\n        \r\n        this._elem.addClass(klass);\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.BlockCanvas.prototype.setContext = function() {\r\n        this._ctx = {\r\n            canvas:{\r\n                width:0,\r\n                height:0\r\n            },\r\n            clearRect:function(){return null;}\r\n        };\r\n        return this._ctx;\r\n    };\r\n    \r\n})(jQuery);\r\n    \r\n    "
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.bubbleRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    var arrayMax = function( array ){\r\n        return Math.max.apply( Math, array );\r\n    };\r\n    var arrayMin = function( array ){\r\n        return Math.min.apply( Math, array );\r\n    };\r\n\r\n    /**\r\n     * Class: $.jqplot.BubbleRenderer\r\n     * Plugin renderer to draw a bubble chart.  A Bubble chart has data points displayed as\r\n     * colored circles with an optional text label inside.  To use\r\n     * the bubble renderer, you must include the bubble renderer like:\r\n     * \r\n     * > <script language=\"javascript\" type=\"text/javascript\" src=\"../src/plugins/jqplot.bubbleRenderer.js\"></script>\r\n     * \r\n     * Data must be supplied in \r\n     * the form:\r\n     * \r\n     * > [[x1, y1, r1, <label or {label:'text', color:color}>], ...]\r\n     * \r\n     * where the label or options \r\n     * object is optional.  \r\n     * \r\n     * Note that all bubble colors will be the same\r\n     * unless the \"varyBubbleColors\" option is set to true.  Colors can be specified in the data array\r\n     * or in the seriesColors array option on the series.  If no colors are defined, the default jqPlot\r\n     * series of 16 colors are used.  Colors are automatically cycled around again if there are more\r\n     * bubbles than colors.\r\n     * \r\n     * Bubbles are autoscaled by default to fit within the chart area while maintaining \r\n     * relative sizes.  If the \"autoscaleBubbles\" option is set to false, the r(adius) values\r\n     * in the data array a treated as literal pixel values for the radii of the bubbles.\r\n     * \r\n     * Properties are passed into the bubble renderer in the rendererOptions object of\r\n     * the series options like:\r\n     * \r\n     * > seriesDefaults: {\r\n     * >     renderer: $.jqplot.BubbleRenderer,\r\n     * >     rendererOptions: {\r\n     * >         bubbleAlpha: 0.7,\r\n     * >         varyBubbleColors: false\r\n     * >     }\r\n     * > }\r\n     * \r\n     */\r\n    $.jqplot.BubbleRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.BubbleRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.BubbleRenderer.prototype.constructor = $.jqplot.BubbleRenderer;\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.BubbleRenderer.prototype.init = function(options, plot) {\r\n        // Group: Properties\r\n        //\r\n        // prop: varyBubbleColors\r\n        // True to vary the color of each bubble in this series according to\r\n        // the seriesColors array.  False to set each bubble to the color\r\n        // specified on this series.  This has no effect if a css background color\r\n        // option is specified in the renderer css options.\r\n        this.varyBubbleColors = true;\r\n        // prop: autoscaleBubbles\r\n        // True to scale the bubble radius based on plot size.\r\n        // False will use the radius value as provided as a raw pixel value for\r\n        // bubble radius.\r\n        this.autoscaleBubbles = true;\r\n        // prop: autoscaleMultiplier\r\n        // Multiplier the bubble size if autoscaleBubbles is true.\r\n        this.autoscaleMultiplier = 1.0;\r\n        // prop: autoscalePointsFactor\r\n        // Factor which decreases bubble size based on how many bubbles on on the chart.\r\n        // 0 means no adjustment for number of bubbles.  Negative values will decrease\r\n        // size of bubbles as more bubbles are added.  Values between 0 and -0.2\r\n        // should work well.\r\n        this.autoscalePointsFactor = -0.07;\r\n        // prop: escapeHtml\r\n        // True to escape html in bubble label text.\r\n        this.escapeHtml = true;\r\n        // prop: highlightMouseOver\r\n        // True to highlight bubbles when moused over.\r\n        // This must be false to enable highlightMouseDown to highlight when clicking on a slice.\r\n        this.highlightMouseOver = true;\r\n        // prop: highlightMouseDown\r\n        // True to highlight when a mouse button is pressed over a bubble.\r\n        // This will be disabled if highlightMouseOver is true.\r\n        this.highlightMouseDown = false;\r\n        // prop: highlightColors\r\n        // An array of colors to use when highlighting a slice.  Calculated automatically\r\n        // if not supplied.\r\n        this.highlightColors = [];\r\n        // prop: bubbleAlpha\r\n        // Alpha transparency to apply to all bubbles in this series.\r\n        this.bubbleAlpha = 1.0;\r\n        // prop: highlightAlpha\r\n        // Alpha transparency to apply when highlighting bubble.\r\n        // Set to value of bubbleAlpha by default.\r\n        this.highlightAlpha = null;\r\n        // prop: bubbleGradients\r\n        // True to color the bubbles with gradient fills instead of flat colors.\r\n        // NOT AVAILABLE IN IE due to lack of excanvas support for radial gradient fills.\r\n        // will be ignored in IE.\r\n        this.bubbleGradients = false;\r\n        // prop: showLabels\r\n        // True to show labels on bubbles (if any), false to not show.\r\n        this.showLabels = true;\r\n        // array of [point index, radius] which will be sorted in descending order to plot \r\n        // largest points below smaller points.\r\n        this.radii = [];\r\n        this.maxRadius = 0;\r\n        // index of the currenty highlighted point, if any\r\n        this._highlightedPoint = null;\r\n        // array of jQuery labels.\r\n        this.labels = [];\r\n        this.bubbleCanvases = [];\r\n        this._type = 'bubble';\r\n        \r\n        // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver\r\n        if (options.highlightMouseDown && options.highlightMouseOver == null) {\r\n            options.highlightMouseOver = false;\r\n        }\r\n        \r\n        $.extend(true, this, options);\r\n        \r\n        if (this.highlightAlpha == null) {\r\n            this.highlightAlpha = this.bubbleAlpha;\r\n            if (this.bubbleGradients) {\r\n                this.highlightAlpha = 0.35;\r\n            }\r\n        }\r\n        \r\n        this.autoscaleMultiplier = this.autoscaleMultiplier * Math.pow(this.data.length, this.autoscalePointsFactor);\r\n        \r\n        // index of the currenty highlighted point, if any\r\n        this._highlightedPoint = null;\r\n        \r\n        // adjust the series colors for options colors passed in with data or for alpha.\r\n        // note, this can leave undefined holes in the seriesColors array.\r\n        var comps;\r\n        for (var i=0; i<this.data.length; i++) {\r\n            var color = null;\r\n            var d = this.data[i];\r\n            this.maxRadius = Math.max(this.maxRadius, d[2]);\r\n            if (d[3]) {\r\n                if (typeof(d[3]) == 'object') {\r\n                    color = d[3]['color'];\r\n                }\r\n            }\r\n            \r\n            if (color == null) {\r\n                if (this.seriesColors[i] != null) {\r\n                    color = this.seriesColors[i];\r\n                }\r\n            }\r\n            \r\n            if (color && this.bubbleAlpha < 1.0) {\r\n                comps = $.jqplot.getColorComponents(color);\r\n                color = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', '+this.bubbleAlpha+')';\r\n            }\r\n            \r\n            if (color) {\r\n                this.seriesColors[i] = color;\r\n            }\r\n        }\r\n        \r\n        if (!this.varyBubbleColors) {\r\n            this.seriesColors = [this.color];\r\n        }\r\n        \r\n        this.colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);\r\n        \r\n        // set highlight colors if none provided\r\n        if (this.highlightColors.length == 0) {\r\n            for (var i=0; i<this.seriesColors.length; i++){\r\n                var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);\r\n                var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n                var sum = newrgb[0] + newrgb[1] + newrgb[2];\r\n                for (var j=0; j<3; j++) {\r\n                    // when darkening, lowest color component can be is 60.\r\n                    newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);\r\n                    newrgb[j] = parseInt(newrgb[j], 10);\r\n                }\r\n                this.highlightColors.push('rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+', '+this.highlightAlpha+')');\r\n            }\r\n        }\r\n        \r\n        this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);\r\n        \r\n        var sopts = {fill:true, isarc:true, angle:this.shadowAngle, alpha:this.shadowAlpha, closePath:true};\r\n        \r\n        this.renderer.shadowRenderer.init(sopts);\r\n        \r\n        this.canvas = new $.jqplot.DivCanvas();\r\n        this.canvas._plotDimensions = this._plotDimensions;\r\n        \r\n        plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);\r\n        plot.eventListenerHooks.addOnce('jqplotClick', handleClick);\r\n        plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);\r\n        plot.postDrawHooks.addOnce(postPlotDraw);\r\n        \r\n    };\r\n    \r\n\r\n    // converts the user data values to grid coordinates and stores them\r\n    // in the gridData array.\r\n    // Called with scope of a series.\r\n    $.jqplot.BubbleRenderer.prototype.setGridData = function(plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var data = this._plotData;\r\n        this.gridData = [];\r\n        var radii = [];\r\n        this.radii = [];\r\n        var dim = Math.min(plot._height, plot._width);\r\n        for (var i=0; i<this.data.length; i++) {\r\n            if (data[i] != null) {\r\n                this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]);\r\n                this.radii.push([i, data[i][2]]);\r\n                radii.push(data[i][2]);\r\n            }\r\n        }\r\n        var r, val, maxr = this.maxRadius = arrayMax(radii);\r\n        var l = this.gridData.length;\r\n        if (this.autoscaleBubbles) {\r\n            for (var i=0; i<l; i++) {\r\n                val = radii[i]/maxr;\r\n                r = this.autoscaleMultiplier * dim / 6;\r\n                this.gridData[i][2] = r * val;\r\n            }\r\n        }\r\n        \r\n        this.radii.sort(function(a, b) { return b[1] - a[1]; });\r\n    };\r\n    \r\n    // converts any arbitrary data values to grid coordinates and\r\n    // returns them.  This method exists so that plugins can use a series'\r\n    // linerenderer to generate grid data points without overwriting the\r\n    // grid data associated with that series.\r\n    // Called with scope of a series.\r\n    $.jqplot.BubbleRenderer.prototype.makeGridData = function(data, plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var gd = [];\r\n        var radii = [];\r\n        this.radii = [];\r\n        var dim = Math.min(plot._height, plot._width);\r\n        for (var i=0; i<data.length; i++) {\r\n            if (data[i] != null) {\r\n                gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1]), data[i][2]]);\r\n                radii.push(data[i][2]);\r\n                this.radii.push([i, data[i][2]]);\r\n            }\r\n        }\r\n        var r, val, maxr = this.maxRadius = arrayMax(radii);\r\n        var l = this.gridData.length;\r\n        if (this.autoscaleBubbles) {\r\n            for (var i=0; i<l; i++) {\r\n                val = radii[i]/maxr;\r\n                r = this.autoscaleMultiplier * dim / 6;\r\n                gd[i][2] = r * val;\r\n            }\r\n        }\r\n        this.radii.sort(function(a, b) { return b[1] - a[1]; });\r\n        return gd;\r\n    };\r\n    \r\n    // called with scope of series\r\n    $.jqplot.BubbleRenderer.prototype.draw = function (ctx, gd, options) {\r\n        if (this.plugins.pointLabels) {\r\n            this.plugins.pointLabels.show = false;\r\n        }\r\n        var opts = (options != undefined) ? options : {};\r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        this.canvas._elem.empty();\r\n        for (var i=0; i<this.radii.length; i++) {\r\n            var idx = this.radii[i][0];\r\n            var t=null;\r\n            var color = null;\r\n            var el = null;\r\n            var tel = null;\r\n            var d = this.data[idx];\r\n            var gd = this.gridData[idx];\r\n            if (d[3]) {\r\n                if (typeof(d[3]) == 'object') {\r\n                    t = d[3]['label'];\r\n                }\r\n                else if (typeof(d[3]) == 'string') {\r\n                    t = d[3];\r\n                }\r\n            }\r\n            \r\n            // color = (this.varyBubbleColors) ? this.colorGenerator.get(idx) : this.color;\r\n            color = this.colorGenerator.get(idx);\r\n            \r\n            // If we're drawing a shadow, expand the canvas dimensions to accomodate.\r\n            var canvasRadius = gd[2];\r\n            var offset, depth;\r\n            if (this.shadow) {\r\n                offset = (0.7 + gd[2]/40).toFixed(1);\r\n                depth = 1 + Math.ceil(gd[2]/15);\r\n                canvasRadius += offset*depth;\r\n            }\r\n            this.bubbleCanvases[idx] = new $.jqplot.BubbleCanvas();\r\n            this.canvas._elem.append(this.bubbleCanvases[idx].createElement(gd[0], gd[1], canvasRadius));\r\n            this.bubbleCanvases[idx].setContext();\r\n            var ctx = this.bubbleCanvases[idx]._ctx;\r\n            var x = ctx.canvas.width/2;\r\n            var y = ctx.canvas.height/2;\r\n            if (this.shadow) {\r\n                this.renderer.shadowRenderer.draw(ctx, [x, y, gd[2], 0, 2*Math.PI], {offset: offset, depth: depth});\r\n            }\r\n            this.bubbleCanvases[idx].draw(gd[2], color, this.bubbleGradients, this.shadowAngle/180*Math.PI);\r\n            \r\n            // now draw label.\r\n            if (t && this.showLabels) {\r\n                tel = $('<div style=\"position:absolute;\" class=\"jqplot-bubble-label\"></div>');\r\n                if (this.escapeHtml) {\r\n                    tel.text(t);\r\n                }\r\n                else {\r\n                    tel.html(t);\r\n                }\r\n                this.canvas._elem.append(tel);\r\n                var h = $(tel).outerHeight();\r\n                var w = $(tel).outerWidth();\r\n                var top = gd[1] - 0.5*h;\r\n                var left = gd[0] - 0.5*w;\r\n                tel.css({top: top, left: left});\r\n                this.labels[idx] = $(tel);\r\n            }\r\n        }\r\n    };\r\n\r\n    \r\n    $.jqplot.DivCanvas = function() {\r\n        $.jqplot.ElemContainer.call(this);\r\n        this._ctx;  \r\n    };\r\n    \r\n    $.jqplot.DivCanvas.prototype = new $.jqplot.ElemContainer();\r\n    $.jqplot.DivCanvas.prototype.constructor = $.jqplot.DivCanvas;\r\n    \r\n    $.jqplot.DivCanvas.prototype.createElement = function(offsets, clss, plotDimensions) {\r\n        this._offsets = offsets;\r\n        var klass = 'jqplot-DivCanvas';\r\n        if (clss != undefined) {\r\n            klass = clss;\r\n        }\r\n        var elem;\r\n        // if this canvas already has a dom element, don't make a new one.\r\n        if (this._elem) {\r\n            elem = this._elem.get(0);\r\n        }\r\n        else {\r\n            elem = document.createElement('div');\r\n        }\r\n        // if new plotDimensions supplied, use them.\r\n        if (plotDimensions != undefined) {\r\n            this._plotDimensions = plotDimensions;\r\n        }\r\n        \r\n        var w = this._plotDimensions.width - this._offsets.left - this._offsets.right + 'px';\r\n        var h = this._plotDimensions.height - this._offsets.top - this._offsets.bottom + 'px';\r\n        this._elem = $(elem);\r\n        this._elem.css({ position: 'absolute', width:w, height:h, left: this._offsets.left, top: this._offsets.top });\r\n        \r\n        this._elem.addClass(klass);\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.DivCanvas.prototype.setContext = function() {\r\n        this._ctx = {\r\n            canvas:{\r\n                width:0,\r\n                height:0\r\n            },\r\n            clearRect:function(){return null;}\r\n        };\r\n        return this._ctx;\r\n    };\r\n    \r\n    $.jqplot.BubbleCanvas = function() {\r\n        $.jqplot.ElemContainer.call(this);\r\n        this._ctx;\r\n    };\r\n    \r\n    $.jqplot.BubbleCanvas.prototype = new $.jqplot.ElemContainer();\r\n    $.jqplot.BubbleCanvas.prototype.constructor = $.jqplot.BubbleCanvas;\r\n    \r\n    // initialize with the x,y pont of bubble center and the bubble radius.\r\n    $.jqplot.BubbleCanvas.prototype.createElement = function(x, y, r) {     \r\n        var klass = 'jqplot-bubble-point';\r\n\r\n        var elem;\r\n        // if this canvas already has a dom element, don't make a new one.\r\n        if (this._elem) {\r\n            elem = this._elem.get(0);\r\n        }\r\n        else {\r\n            elem = document.createElement('canvas');\r\n        }\r\n        \r\n        elem.width = (r != null) ? 2*r : elem.width;\r\n        elem.height = (r != null) ? 2*r : elem.height;\r\n        this._elem = $(elem);\r\n        var l = (x != null && r != null) ? x - r : this._elem.css('left');\r\n        var t = (y != null && r != null) ? y - r : this._elem.css('top');\r\n        this._elem.css({ position: 'absolute', left: l, top: t });\r\n        \r\n        this._elem.addClass(klass);\r\n        if ($.jqplot.use_excanvas) {\r\n            window.G_vmlCanvasManager.init_(document);\r\n            elem = window.G_vmlCanvasManager.initElement(elem);\r\n        }\r\n        \r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.BubbleCanvas.prototype.draw = function(r, color, gradients, angle) {\r\n        var ctx = this._ctx;\r\n        // r = Math.floor(r*1.04);\r\n        // var x = Math.round(ctx.canvas.width/2);\r\n        // var y = Math.round(ctx.canvas.height/2);\r\n        var x = ctx.canvas.width/2;\r\n        var y = ctx.canvas.height/2;\r\n        ctx.save();\r\n        if (gradients && !$.jqplot.use_excanvas) {\r\n            r = r*1.04;\r\n            var comps = $.jqplot.getColorComponents(color);\r\n            var colorinner = 'rgba('+Math.round(comps[0]+0.8*(255-comps[0]))+', '+Math.round(comps[1]+0.8*(255-comps[1]))+', '+Math.round(comps[2]+0.8*(255-comps[2]))+', '+comps[3]+')';\r\n            var colorend = 'rgba('+comps[0]+', '+comps[1]+', '+comps[2]+', 0)';\r\n            // var rinner = Math.round(0.35 * r);\r\n            // var xinner = Math.round(x - Math.cos(angle) * 0.33 * r);\r\n            // var yinner = Math.round(y - Math.sin(angle) * 0.33 * r);\r\n            var rinner = 0.35 * r;\r\n            var xinner = x - Math.cos(angle) * 0.33 * r;\r\n            var yinner = y - Math.sin(angle) * 0.33 * r;\r\n            var radgrad = ctx.createRadialGradient(xinner, yinner, rinner, x, y, r);\r\n            radgrad.addColorStop(0, colorinner);\r\n            radgrad.addColorStop(0.93, color);\r\n            radgrad.addColorStop(0.96, colorend);\r\n            radgrad.addColorStop(1, colorend);\r\n            // radgrad.addColorStop(.98, colorend);\r\n            ctx.fillStyle = radgrad;\r\n            ctx.fillRect(0,0, ctx.canvas.width, ctx.canvas.height);\r\n        }\r\n        else {\r\n            ctx.fillStyle = color;\r\n            ctx.strokeStyle = color;\r\n            ctx.lineWidth = 1;\r\n            ctx.beginPath();\r\n            var ang = 2*Math.PI;\r\n            ctx.arc(x, y, r, 0, ang, 0);\r\n            ctx.closePath();\r\n            ctx.fill();\r\n        }\r\n        ctx.restore();\r\n    };\r\n    \r\n    $.jqplot.BubbleCanvas.prototype.setContext = function() {\r\n        this._ctx = this._elem.get(0).getContext(\"2d\");\r\n        return this._ctx;\r\n    };\r\n    \r\n    $.jqplot.BubbleAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.BubbleAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.BubbleAxisRenderer.prototype.constructor = $.jqplot.BubbleAxisRenderer;\r\n        \r\n    // called with scope of axis object.\r\n    $.jqplot.BubbleAxisRenderer.prototype.init = function(options){\r\n        $.extend(true, this, options);\r\n        var db = this._dataBounds;\r\n        var minsidx = 0,\r\n            minpidx = 0,\r\n            maxsidx = 0,\r\n            maxpidx = 0,\r\n            maxr = 0,\r\n            minr = 0,\r\n            minMaxRadius = 0,\r\n            maxMaxRadius = 0,\r\n            maxMult = 0,\r\n            minMult = 0;\r\n        // Go through all the series attached to this axis and find\r\n        // the min/max bounds for this axis.\r\n        for (var i=0; i<this._series.length; i++) {\r\n            var s = this._series[i];\r\n            var d = s._plotData;\r\n            \r\n            for (var j=0; j<d.length; j++) { \r\n                if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                    if (d[j][0] < db.min || db.min == null) {\r\n                        db.min = d[j][0];\r\n                        minsidx=i;\r\n                        minpidx=j;\r\n                        minr = d[j][2];\r\n                        minMaxRadius = s.maxRadius;\r\n                        minMult = s.autoscaleMultiplier;\r\n                    }\r\n                    if (d[j][0] > db.max || db.max == null) {\r\n                        db.max = d[j][0];\r\n                        maxsidx=i;\r\n                        maxpidx=j;\r\n                        maxr = d[j][2];\r\n                        maxMaxRadius = s.maxRadius;\r\n                        maxMult = s.autoscaleMultiplier;\r\n                    }\r\n                }              \r\n                else {\r\n                    if (d[j][1] < db.min || db.min == null) {\r\n                        db.min = d[j][1];\r\n                        minsidx=i;\r\n                        minpidx=j;\r\n                        minr = d[j][2];\r\n                        minMaxRadius = s.maxRadius;\r\n                        minMult = s.autoscaleMultiplier;\r\n                    }\r\n                    if (d[j][1] > db.max || db.max == null) {\r\n                        db.max = d[j][1];\r\n                        maxsidx=i;\r\n                        maxpidx=j;\r\n                        maxr = d[j][2];\r\n                        maxMaxRadius = s.maxRadius;\r\n                        maxMult = s.autoscaleMultiplier;\r\n                    }\r\n                }              \r\n            }\r\n        }\r\n        \r\n        var minRatio = minr/minMaxRadius;\r\n        var maxRatio = maxr/maxMaxRadius;\r\n        \r\n        // need to estimate the effect of the radius on total axis span and adjust axis accordingly.\r\n        var span = db.max - db.min;\r\n        // var dim = (this.name == 'xaxis' || this.name == 'x2axis') ? this._plotDimensions.width : this._plotDimensions.height;\r\n        var dim = Math.min(this._plotDimensions.width, this._plotDimensions.height);\r\n        \r\n        var minfact = minRatio * minMult/3 * span;\r\n        var maxfact = maxRatio * maxMult/3 * span;\r\n        db.max += maxfact;\r\n        db.min -= minfact;\r\n    };\r\n    \r\n    function highlight (plot, sidx, pidx) {\r\n        plot.plugins.bubbleRenderer.highlightLabelCanvas.empty();\r\n        var s = plot.series[sidx];\r\n        var canvas = plot.plugins.bubbleRenderer.highlightCanvas;\r\n        var ctx = canvas._ctx;\r\n        ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n        s._highlightedPoint = pidx;\r\n        plot.plugins.bubbleRenderer.highlightedSeriesIndex = sidx;\r\n        \r\n        var color = s.highlightColorGenerator.get(pidx);\r\n        var x = s.gridData[pidx][0],\r\n            y = s.gridData[pidx][1],\r\n            r = s.gridData[pidx][2];\r\n        ctx.save();\r\n        ctx.fillStyle = color;\r\n        ctx.strokeStyle = color;\r\n        ctx.lineWidth = 1;\r\n        ctx.beginPath();\r\n        ctx.arc(x, y, r, 0, 2*Math.PI, 0);\r\n        ctx.closePath();\r\n        ctx.fill();\r\n        ctx.restore();        \r\n        // bring label to front\r\n        if (s.labels[pidx]) {\r\n            plot.plugins.bubbleRenderer.highlightLabel = s.labels[pidx].clone();\r\n            plot.plugins.bubbleRenderer.highlightLabel.appendTo(plot.plugins.bubbleRenderer.highlightLabelCanvas);\r\n            plot.plugins.bubbleRenderer.highlightLabel.addClass('jqplot-bubble-label-highlight');\r\n        }\r\n    }\r\n    \r\n    function unhighlight (plot) {\r\n        var canvas = plot.plugins.bubbleRenderer.highlightCanvas;\r\n        var sidx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;\r\n        plot.plugins.bubbleRenderer.highlightLabelCanvas.empty();\r\n        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            plot.series[i]._highlightedPoint = null;\r\n        }\r\n        plot.plugins.bubbleRenderer.highlightedSeriesIndex = null;\r\n        plot.target.trigger('jqplotDataUnhighlight');\r\n    }\r\n    \r\n \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var si = neighbor.seriesIndex;\r\n            var pi = neighbor.pointIndex;\r\n            var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];\r\n            var evt1 = jQuery.Event('jqplotDataMouseOver');\r\n            evt1.pageX = ev.pageX;\r\n            evt1.pageY = ev.pageY;\r\n            plot.target.trigger(evt1, ins);\r\n            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    } \r\n    \r\n    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var si = neighbor.seriesIndex;\r\n            var pi = neighbor.pointIndex;\r\n            var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];\r\n            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.bubbleRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {\r\n        var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;\r\n        if (idx != null && plot.series[idx].highlightMouseDown) {\r\n            unhighlight(plot);\r\n        }\r\n    }\r\n    \r\n    function handleClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var si = neighbor.seriesIndex;\r\n            var pi = neighbor.pointIndex;\r\n            var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];\r\n            var evt = jQuery.Event('jqplotDataClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var si = neighbor.seriesIndex;\r\n            var pi = neighbor.pointIndex;\r\n            var ins = [si, pi, neighbor.data, plot.series[si].gridData[pi][2]];\r\n            var idx = plot.plugins.bubbleRenderer.highlightedSeriesIndex;\r\n            if (idx != null && plot.series[idx].highlightMouseDown) {\r\n                unhighlight(plot);\r\n            }\r\n            var evt = jQuery.Event('jqplotDataRightClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    function postPlotDraw() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.bubbleRenderer && this.plugins.bubbleRenderer.highlightCanvas) {\r\n            this.plugins.bubbleRenderer.highlightCanvas.resetCanvas();\r\n            this.plugins.bubbleRenderer.highlightCanvas = null;\r\n        }\r\n        \r\n        this.plugins.bubbleRenderer = {highlightedSeriesIndex:null};\r\n        this.plugins.bubbleRenderer.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        this.plugins.bubbleRenderer.highlightLabel = null;\r\n        this.plugins.bubbleRenderer.highlightLabelCanvas = $('<div style=\"position:absolute;\"></div>');\r\n        var top = this._gridPadding.top;\r\n        var left = this._gridPadding.left;\r\n        var width = this._plotDimensions.width - this._gridPadding.left - this._gridPadding.right;\r\n        var height = this._plotDimensions.height - this._gridPadding.top - this._gridPadding.bottom;\r\n        this.plugins.bubbleRenderer.highlightLabelCanvas.css({top:top, left:left, width:width+'px', height:height+'px'});\r\n\r\n        this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-bubbleRenderer-highlight-canvas', this._plotDimensions, this));\r\n        this.eventCanvas._elem.before(this.plugins.bubbleRenderer.highlightLabelCanvas);\r\n        \r\n        var hctx = this.plugins.bubbleRenderer.highlightCanvas.setContext();\r\n    }\r\n\r\n    \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        options = options || {};\r\n        options.axesDefaults = options.axesDefaults || {};\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        // only set these if there is a Bubble series\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer == $.jqplot.BubbleRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer == $.jqplot.BubbleRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.BubbleAxisRenderer;\r\n            options.sortData = false;\r\n        }\r\n    }\r\n    \r\n    $.jqplot.preInitHooks.push(preInit);\r\n    \r\n})(jQuery);\r\n    \r\n    "
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.canvasAxisLabelRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n    * Class: $.jqplot.CanvasAxisLabelRenderer\r\n    * Renderer to draw axis labels with a canvas element to support advanced\r\n    * featrues such as rotated text.  This renderer uses a separate rendering engine\r\n    * to draw the text on the canvas.  Two modes of rendering the text are available.\r\n    * If the browser has native font support for canvas fonts (currently Mozila 3.5\r\n    * and Safari 4), you can enable text rendering with the canvas fillText method.\r\n    * You do so by setting the \"enableFontSupport\" option to true. \r\n    * \r\n    * Browsers lacking native font support will have the text drawn on the canvas\r\n    * using the Hershey font metrics.  Even if the \"enableFontSupport\" option is true\r\n    * non-supporting browsers will still render with the Hershey font.\r\n    * \r\n    */\r\n    $.jqplot.CanvasAxisLabelRenderer = function(options) {\r\n        // Group: Properties\r\n        \r\n        // prop: angle\r\n        // angle of text, measured clockwise from x axis.\r\n        this.angle = 0;\r\n        // name of the axis associated with this tick\r\n        this.axis;\r\n        // prop: show\r\n        // whether or not to show the tick (mark and label).\r\n        this.show = true;\r\n        // prop: showLabel\r\n        // whether or not to show the label.\r\n        this.showLabel = true;\r\n        // prop: label\r\n        // label for the axis.\r\n        this.label = '';\r\n        // prop: fontFamily\r\n        // CSS spec for the font-family css attribute.\r\n        // Applies only to browsers supporting native font rendering in the\r\n        // canvas tag.  Currently Mozilla 3.5 and Safari 4.\r\n        this.fontFamily = '\"Trebuchet MS\", Arial, Helvetica, sans-serif';\r\n        // prop: fontSize\r\n        // CSS spec for font size.\r\n        this.fontSize = '11pt';\r\n        // prop: fontWeight\r\n        // CSS spec for fontWeight:  normal, bold, bolder, lighter or a number 100 - 900\r\n        this.fontWeight = 'normal';\r\n        // prop: fontStretch\r\n        // Multiplier to condense or expand font width.  \r\n        // Applies only to browsers which don't support canvas native font rendering.\r\n        this.fontStretch = 1.0;\r\n        // prop: textColor\r\n        // css spec for the color attribute.\r\n        this.textColor = '#666666';\r\n        // prop: enableFontSupport\r\n        // true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.\r\n        // If true, label will be drawn with canvas tag native support for fonts.\r\n        // If false, label will be drawn with Hershey font metrics.\r\n        this.enableFontSupport = true;\r\n        // prop: pt2px\r\n        // Point to pixel scaling factor, used for computing height of bounding box\r\n        // around a label.  The labels text renderer has a default setting of 1.4, which \r\n        // should be suitable for most fonts.  Leave as null to use default.  If tops of\r\n        // letters appear clipped, increase this.  If bounding box seems too big, decrease.\r\n        // This is an issue only with the native font renderering capabilities of Mozilla\r\n        // 3.5 and Safari 4 since they do not provide a method to determine the font height.\r\n        this.pt2px = null;\r\n        \r\n        this._elem;\r\n        this._ctx;\r\n        this._plotWidth;\r\n        this._plotHeight;\r\n        this._plotDimensions = {height:null, width:null};\r\n        \r\n        $.extend(true, this, options);\r\n        \r\n        if (options.angle == null && this.axis != 'xaxis' && this.axis != 'x2axis') {\r\n            this.angle = -90;\r\n        }\r\n        \r\n        var ropts = {fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily};\r\n        if (this.pt2px) {\r\n            ropts.pt2px = this.pt2px;\r\n        }\r\n        \r\n        if (this.enableFontSupport) {\r\n            if ($.jqplot.support_canvas_text()) {\r\n                this._textRenderer = new $.jqplot.CanvasFontRenderer(ropts);\r\n            }\r\n            \r\n            else {\r\n                this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); \r\n            }\r\n        }\r\n        else {\r\n            this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); \r\n        }\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisLabelRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n        this._textRenderer.init({fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily});\r\n    };\r\n    \r\n    // return width along the x axis\r\n    // will check first to see if an element exists.\r\n    // if not, will return the computed text box width.\r\n    $.jqplot.CanvasAxisLabelRenderer.prototype.getWidth = function(ctx) {\r\n        if (this._elem) {\r\n         return this._elem.outerWidth(true);\r\n        }\r\n        else {\r\n            var tr = this._textRenderer;\r\n            var l = tr.getWidth(ctx);\r\n            var h = tr.getHeight(ctx);\r\n            var w = Math.abs(Math.sin(tr.angle)*h) + Math.abs(Math.cos(tr.angle)*l);\r\n            return w;\r\n        }\r\n    };\r\n    \r\n    // return height along the y axis.\r\n    $.jqplot.CanvasAxisLabelRenderer.prototype.getHeight = function(ctx) {\r\n        if (this._elem) {\r\n         return this._elem.outerHeight(true);\r\n        }\r\n        else {\r\n            var tr = this._textRenderer;\r\n            var l = tr.getWidth(ctx);\r\n            var h = tr.getHeight(ctx);\r\n            var w = Math.abs(Math.cos(tr.angle)*h) + Math.abs(Math.sin(tr.angle)*l);\r\n            return w;\r\n        }\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad = function() {\r\n        var a = this.angle * Math.PI/180;\r\n        return a;\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisLabelRenderer.prototype.draw = function(ctx, plot) {\r\n          // Memory Leaks patch\r\n          if (this._elem) {\r\n              if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {\r\n                  window.G_vmlCanvasManager.uninitElement(this._elem.get(0));\r\n              }\r\n            \r\n              this._elem.emptyForce();\r\n              this._elem = null;\r\n          }\r\n\r\n        // create a canvas here, but can't draw on it untill it is appended\r\n        // to dom for IE compatability.\r\n        var elem = plot.canvasManager.getCanvas();\r\n\r\n        this._textRenderer.setText(this.label, ctx);\r\n        var w = this.getWidth(ctx);\r\n        var h = this.getHeight(ctx);\r\n        elem.width = w;\r\n        elem.height = h;\r\n        elem.style.width = w;\r\n        elem.style.height = h;\r\n        \r\n        elem = plot.canvasManager.initCanvas(elem);\r\n\r\n        this._elem = $(elem);\r\n        this._elem.css({ position: 'absolute'});\r\n        this._elem.addClass('jqplot-'+this.axis+'-label');\r\n        \r\n        elem = null;\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisLabelRenderer.prototype.pack = function() {\r\n        this._textRenderer.draw(this._elem.get(0).getContext(\"2d\"), this.label);\r\n    };\r\n    \r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.canvasAxisTickRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n    *  Class: $.jqplot.CanvasAxisTickRenderer\r\n    * Renderer to draw axis ticks with a canvas element to support advanced\r\n    * featrues such as rotated text.  This renderer uses a separate rendering engine\r\n    * to draw the text on the canvas.  Two modes of rendering the text are available.\r\n    * If the browser has native font support for canvas fonts (currently Mozila 3.5\r\n    * and Safari 4), you can enable text rendering with the canvas fillText method.\r\n    * You do so by setting the \"enableFontSupport\" option to true. \r\n    * \r\n    * Browsers lacking native font support will have the text drawn on the canvas\r\n    * using the Hershey font metrics.  Even if the \"enableFontSupport\" option is true\r\n    * non-supporting browsers will still render with the Hershey font.\r\n    */\r\n    $.jqplot.CanvasAxisTickRenderer = function(options) {\r\n        // Group: Properties\r\n        \r\n        // prop: mark\r\n        // tick mark on the axis.  One of 'inside', 'outside', 'cross', '' or null.\r\n        this.mark = 'outside';\r\n        // prop: showMark\r\n        // whether or not to show the mark on the axis.\r\n        this.showMark = true;\r\n        // prop: showGridline\r\n        // whether or not to draw the gridline on the grid at this tick.\r\n        this.showGridline = true;\r\n        // prop: isMinorTick\r\n        // if this is a minor tick.\r\n        this.isMinorTick = false;\r\n        // prop: angle\r\n        // angle of text, measured clockwise from x axis.\r\n        this.angle = 0;\r\n        // prop:  markSize\r\n        // Length of the tick marks in pixels.  For 'cross' style, length\r\n        // will be stoked above and below axis, so total length will be twice this.\r\n        this.markSize = 4;\r\n        // prop: show\r\n        // whether or not to show the tick (mark and label).\r\n        this.show = true;\r\n        // prop: showLabel\r\n        // whether or not to show the label.\r\n        this.showLabel = true;\r\n        // prop: labelPosition\r\n        // 'auto', 'start', 'middle' or 'end'.\r\n        // Whether tick label should be positioned so the start, middle, or end\r\n        // of the tick mark.\r\n        this.labelPosition = 'auto';\r\n        this.label = '';\r\n        this.value = null;\r\n        this._styles = {};\r\n        // prop: formatter\r\n        // A class of a formatter for the tick text.\r\n        // The default $.jqplot.DefaultTickFormatter uses sprintf.\r\n        this.formatter = $.jqplot.DefaultTickFormatter;\r\n        // prop: formatString\r\n        // string passed to the formatter.\r\n        this.formatString = '';\r\n        // prop: prefix\r\n        // String to prepend to the tick label.\r\n        // Prefix is prepended to the formatted tick label.\r\n        this.prefix = '';\r\n        // prop: fontFamily\r\n        // css spec for the font-family css attribute.\r\n        this.fontFamily = '\"Trebuchet MS\", Arial, Helvetica, sans-serif';\r\n        // prop: fontSize\r\n        // CSS spec for font size.\r\n        this.fontSize = '10pt';\r\n        // prop: fontWeight\r\n        // CSS spec for fontWeight\r\n        this.fontWeight = 'normal';\r\n        // prop: fontStretch\r\n        // Multiplier to condense or expand font width.  \r\n        // Applies only to browsers which don't support canvas native font rendering.\r\n        this.fontStretch = 1.0;\r\n        // prop: textColor\r\n        // css spec for the color attribute.\r\n        this.textColor = '#666666';\r\n        // prop: enableFontSupport\r\n        // true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+.\r\n        // If true, tick label will be drawn with canvas tag native support for fonts.\r\n        // If false, tick label will be drawn with Hershey font metrics.\r\n        this.enableFontSupport = true;\r\n        // prop: pt2px\r\n        // Point to pixel scaling factor, used for computing height of bounding box\r\n        // around a label.  The labels text renderer has a default setting of 1.4, which \r\n        // should be suitable for most fonts.  Leave as null to use default.  If tops of\r\n        // letters appear clipped, increase this.  If bounding box seems too big, decrease.\r\n        // This is an issue only with the native font renderering capabilities of Mozilla\r\n        // 3.5 and Safari 4 since they do not provide a method to determine the font height.\r\n        this.pt2px = null;\r\n        \r\n        this._elem;\r\n        this._ctx;\r\n        this._plotWidth;\r\n        this._plotHeight;\r\n        this._plotDimensions = {height:null, width:null};\r\n        \r\n        $.extend(true, this, options);\r\n        \r\n        var ropts = {fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily};\r\n        if (this.pt2px) {\r\n            ropts.pt2px = this.pt2px;\r\n        }\r\n        \r\n        if (this.enableFontSupport) {\r\n            if ($.jqplot.support_canvas_text()) {\r\n                this._textRenderer = new $.jqplot.CanvasFontRenderer(ropts);\r\n            }\r\n            \r\n            else {\r\n                this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); \r\n            }\r\n        }\r\n        else {\r\n            this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); \r\n        }\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisTickRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n        this._textRenderer.init({fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily});\r\n    };\r\n    \r\n    // return width along the x axis\r\n    // will check first to see if an element exists.\r\n    // if not, will return the computed text box width.\r\n    $.jqplot.CanvasAxisTickRenderer.prototype.getWidth = function(ctx) {\r\n        if (this._elem) {\r\n         return this._elem.outerWidth(true);\r\n        }\r\n        else {\r\n            var tr = this._textRenderer;\r\n            var l = tr.getWidth(ctx);\r\n            var h = tr.getHeight(ctx);\r\n            var w = Math.abs(Math.sin(tr.angle)*h) + Math.abs(Math.cos(tr.angle)*l);\r\n            return w;\r\n        }\r\n    };\r\n    \r\n    // return height along the y axis.\r\n    $.jqplot.CanvasAxisTickRenderer.prototype.getHeight = function(ctx) {\r\n        if (this._elem) {\r\n         return this._elem.outerHeight(true);\r\n        }\r\n        else {\r\n            var tr = this._textRenderer;\r\n            var l = tr.getWidth(ctx);\r\n            var h = tr.getHeight(ctx);\r\n            var w = Math.abs(Math.cos(tr.angle)*h) + Math.abs(Math.sin(tr.angle)*l);\r\n            return w;\r\n        }\r\n    };\r\n\r\n    // return top.\r\n    $.jqplot.CanvasAxisTickRenderer.prototype.getTop = function(ctx) {\r\n        if (this._elem) {\r\n         return this._elem.position().top;\r\n        }\r\n        else {\r\n            return null;\r\n        }\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad = function() {\r\n        var a = this.angle * Math.PI/180;\r\n        return a;\r\n    };\r\n    \r\n    \r\n    $.jqplot.CanvasAxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) {\r\n        this.value = value;\r\n        if (isMinor) {\r\n            this.isMinorTick = true;\r\n        }\r\n        return this;\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisTickRenderer.prototype.draw = function(ctx, plot) {\r\n        if (!this.label) {\r\n            this.label = this.prefix + this.formatter(this.formatString, this.value);\r\n        }\r\n        \r\n        // Memory Leaks patch\r\n        if (this._elem) {\r\n            if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) {\r\n                window.G_vmlCanvasManager.uninitElement(this._elem.get(0));\r\n            }\r\n            \r\n            this._elem.emptyForce();\r\n            this._elem = null;\r\n        }\r\n\r\n        // create a canvas here, but can't draw on it untill it is appended\r\n        // to dom for IE compatability.\r\n\r\n        var elem = plot.canvasManager.getCanvas();\r\n\r\n        this._textRenderer.setText(this.label, ctx);\r\n        var w = this.getWidth(ctx);\r\n        var h = this.getHeight(ctx);\r\n        // canvases seem to need to have width and heigh attributes directly set.\r\n        elem.width = w;\r\n        elem.height = h;\r\n        elem.style.width = w;\r\n        elem.style.height = h;\r\n        elem.style.textAlign = 'left';\r\n        elem.style.position = 'absolute';\r\n\r\n        elem = plot.canvasManager.initCanvas(elem);\r\n\r\n        this._elem = $(elem);\r\n        this._elem.css(this._styles);\r\n        this._elem.addClass('jqplot-'+this.axis+'-tick');\r\n\r\n        elem = null;\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.CanvasAxisTickRenderer.prototype.pack = function() {\r\n        this._textRenderer.draw(this._elem.get(0).getContext(\"2d\"), this.label);\r\n    };\r\n    \r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.canvasOverlay.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    var objCounter = 0;\r\n    // class: $.jqplot.CanvasOverlay\r\n    $.jqplot.CanvasOverlay = function(opts){\r\n        var options = opts || {};\r\n        this.options = {\r\n            show: $.jqplot.config.enablePlugins,\r\n            deferDraw: false\r\n        };\r\n        // prop: objects\r\n        this.objects = [];\r\n        this.objectNames = [];\r\n        this.canvas = null;\r\n        this.markerRenderer = new $.jqplot.MarkerRenderer({style:'line'});\r\n        this.markerRenderer.init();\r\n        this.highlightObjectIndex = null;\r\n        if (options.objects) {\r\n            var objs = options.objects,\r\n                obj;\r\n            for (var i=0; i<objs.length; i++) {\r\n                obj = objs[i];\r\n                for (var n in obj) {\r\n                    switch (n) {\r\n                        case 'line':\r\n                            this.addLine(obj[n]);\r\n                            break;\r\n                        case 'horizontalLine':\r\n                            this.addHorizontalLine(obj[n]);\r\n                            break;\r\n                        case 'dashedHorizontalLine':\r\n                            this.addDashedHorizontalLine(obj[n]);\r\n                            break;\r\n                        case 'verticalLine':\r\n                            this.addVerticalLine(obj[n]);\r\n                            break;\r\n                        case 'dashedVerticalLine':\r\n                            this.addDashedVerticalLine(obj[n]);\r\n                            break;\r\n                        case 'rectangle':\r\n                            this.addRectangle(obj[n]);\r\n                            break;\r\n                        default:\r\n                            break;\r\n                    }\r\n                }   \r\n            }\r\n        }\r\n        $.extend(true, this.options, options);\r\n    };\r\n    \r\n    // called with scope of a plot object\r\n    $.jqplot.CanvasOverlay.postPlotInit = function (target, data, opts) {\r\n        var options = opts || {};\r\n        // add a canvasOverlay attribute to the plot\r\n        this.plugins.canvasOverlay = new $.jqplot.CanvasOverlay(options.canvasOverlay);     \r\n    };\r\n\r\n\r\n    function LineBase() {\r\n        this.uid = null;\r\n        this.type = null;\r\n        this.gridStart = null;\r\n        this.gridStop = null;\r\n        this.tooltipWidthFactor = 0;\r\n        this.options = {           \r\n            // prop: name\r\n            // Optional name for the overlay object.\r\n            // Can be later used to retrieve the object by name.\r\n            name: null,\r\n            // prop: show\r\n            // true to show (draw), false to not draw.\r\n            show: true,\r\n            // prop: lineWidth\r\n            // Width of the line.\r\n            lineWidth: 2,\r\n            // prop: lineCap\r\n            // Type of ending placed on the line ['round', 'butt', 'square']\r\n            lineCap: 'round',\r\n            // prop: color\r\n            // color of the line\r\n            color: '#666666',\r\n            // prop: shadow\r\n            // whether or not to draw a shadow on the line\r\n            shadow: true,\r\n            // prop: shadowAngle\r\n            // Shadow angle in degrees\r\n            shadowAngle: 45,\r\n            // prop: shadowOffset\r\n            // Shadow offset from line in pixels\r\n            shadowOffset: 1,\r\n            // prop: shadowDepth\r\n            // Number of times shadow is stroked, each stroke offset shadowOffset from the last.\r\n            shadowDepth: 3,\r\n            // prop: shadowAlpha\r\n            // Alpha channel transparency of shadow.  0 = transparent.\r\n            shadowAlpha: '0.07',\r\n            // prop: xaxis\r\n            // X axis to use for positioning/scaling the line.\r\n            xaxis: 'xaxis',\r\n            // prop: yaxis\r\n            // Y axis to use for positioning/scaling the line.\r\n            yaxis: 'yaxis',\r\n            // prop: showTooltip\r\n            // Show a tooltip with data point values.\r\n            showTooltip: false,\r\n            // prop: showTooltipPrecision\r\n            // Controls how close to line cursor must be to show tooltip.\r\n            // Higher number = closer to line, lower number = farther from line.\r\n            // 1.0 = cursor must be over line.\r\n            showTooltipPrecision: 0.6,\r\n            // prop: tooltipLocation\r\n            // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'\r\n            tooltipLocation: 'nw',\r\n            // prop: fadeTooltip\r\n            // true = fade in/out tooltip, flase = show/hide tooltip\r\n            fadeTooltip: true,\r\n            // prop: tooltipFadeSpeed\r\n            // 'slow', 'def', 'fast', or number of milliseconds.\r\n            tooltipFadeSpeed: \"fast\",\r\n            // prop: tooltipOffset\r\n            // Pixel offset of tooltip from the highlight.\r\n            tooltipOffset: 4,\r\n            // prop: tooltipFormatString\r\n            // Format string passed the x and y values of the cursor on the line.\r\n            // e.g., 'Dogs: %.2f, Cats: %d'.\r\n            tooltipFormatString: '%d, %d'\r\n        };\r\n    }\r\n    \r\n    \r\n    function Rectangle(options) {\r\n        LineBase.call(this);\r\n        this.type = 'rectangle';\r\n        var opts = {\r\n         // prop: xmin\r\n                // x value for the start of the line, null to scale to axis min.\r\n                xmin: null,\r\n                // prop: xmax\r\n                // x value for the end of the line, null to scale to axis max.\r\n                xmax: null,\r\n                // prop xOffset\r\n                // offset ends of the line inside the grid. Number\r\n                xOffset: '6px', // number or string. Number interpreted as units, string as pixels.\r\n                xminOffset: null,\r\n                xmaxOffset: null,\r\n                \r\n                ymin: null,\r\n                ymax: null,\r\n                yOffset: '6px', // number or string. Number interpreted as units, string as pixels.\r\n                yminOffset: null,\r\n                ymaxOffset: null\r\n        };\r\n        $.extend(true, this.options, opts, options);\r\n\r\n        if (this.options.showTooltipPrecision < 0.01) {\r\n            this.options.showTooltipPrecision = 0.01;\r\n        }\r\n    }\r\n\r\n    Rectangle.prototype = new LineBase();\r\n    Rectangle.prototype.constructor = Rectangle;\r\n\r\n    \r\n    /**\r\n     * Class: Line\r\n     * A straight line.\r\n     */\r\n    function Line(options) {\r\n        LineBase.call(this);\r\n        this.type = 'line';\r\n        var opts = {\r\n            // prop: start\r\n            // [x, y] coordinates for the start of the line.\r\n            start: [],\r\n            // prop: stop\r\n            // [x, y] coordinates for the end of the line.\r\n            stop: []\r\n        };\r\n        $.extend(true, this.options, opts, options);\r\n\r\n        if (this.options.showTooltipPrecision < 0.01) {\r\n            this.options.showTooltipPrecision = 0.01;\r\n        }\r\n    }\r\n\r\n    Line.prototype = new LineBase();\r\n    Line.prototype.constructor = Line;\r\n\r\n\r\n    /**\r\n     * Class: HorizontalLine\r\n     * A straight horizontal line.\r\n     */\r\n    function HorizontalLine(options) {\r\n        LineBase.call(this);\r\n        this.type = 'horizontalLine';\r\n        var opts = {\r\n            // prop: y\r\n            // y value to position the line\r\n            y: null,\r\n            // prop: xmin\r\n            // x value for the start of the line, null to scale to axis min.\r\n            xmin: null,\r\n            // prop: xmax\r\n            // x value for the end of the line, null to scale to axis max.\r\n            xmax: null,\r\n            // prop xOffset\r\n            // offset ends of the line inside the grid.  Number \r\n            xOffset: '6px', // number or string.  Number interpreted as units, string as pixels.\r\n            xminOffset: null,\r\n            xmaxOffset: null\r\n        };\r\n        $.extend(true, this.options, opts, options);\r\n\r\n        if (this.options.showTooltipPrecision < 0.01) {\r\n            this.options.showTooltipPrecision = 0.01;\r\n        }\r\n    }\r\n\r\n    HorizontalLine.prototype = new LineBase();\r\n    HorizontalLine.prototype.constructor = HorizontalLine;\r\n    \r\n\r\n    /**\r\n     * Class: DashedHorizontalLine\r\n     * A straight dashed horizontal line.\r\n     */\r\n    function DashedHorizontalLine(options) {\r\n        LineBase.call(this);\r\n        this.type = 'dashedHorizontalLine';\r\n        var opts = {\r\n            y: null,\r\n            xmin: null,\r\n            xmax: null,\r\n            xOffset: '6px', // number or string.  Number interpreted as units, string as pixels.\r\n            xminOffset: null,\r\n            xmaxOffset: null,\r\n            // prop: dashPattern\r\n            // Array of line, space settings in pixels.\r\n            // Default is 8 pixel of line, 8 pixel of space.\r\n            // Note, limit to a 2 element array b/c of bug with higher order arrays.\r\n            dashPattern: [8,8]\r\n        };\r\n        $.extend(true, this.options, opts, options);\r\n\r\n        if (this.options.showTooltipPrecision < 0.01) {\r\n            this.options.showTooltipPrecision = 0.01;\r\n        }\r\n    }\r\n\r\n    DashedHorizontalLine.prototype = new LineBase();\r\n    DashedHorizontalLine.prototype.constructor = DashedHorizontalLine;\r\n    \r\n\r\n    /**\r\n     * Class: VerticalLine\r\n     * A straight vertical line.\r\n     */\r\n    function VerticalLine(options) {\r\n        LineBase.call(this);\r\n        this.type = 'verticalLine';\r\n        var opts = {\r\n            x: null,\r\n            ymin: null,\r\n            ymax: null,\r\n            yOffset: '6px', // number or string.  Number interpreted as units, string as pixels.\r\n            yminOffset: null,\r\n            ymaxOffset: null\r\n        };\r\n        $.extend(true, this.options, opts, options);\r\n\r\n        if (this.options.showTooltipPrecision < 0.01) {\r\n            this.options.showTooltipPrecision = 0.01;\r\n        }\r\n    }\r\n\r\n    VerticalLine.prototype = new LineBase();\r\n    VerticalLine.prototype.constructor = VerticalLine;\r\n    \r\n\r\n    /**\r\n     * Class: DashedVerticalLine\r\n     * A straight dashed vertical line.\r\n     */\r\n    function DashedVerticalLine(options) {\r\n        LineBase.call(this);\r\n        this.type = 'dashedVerticalLine';\r\n        this.start = null;\r\n        this.stop = null;\r\n        var opts = {\r\n            x: null,\r\n            ymin: null,\r\n            ymax: null,\r\n            yOffset: '6px', // number or string.  Number interpreted as units, string as pixels.\r\n            yminOffset: null,\r\n            ymaxOffset: null,\r\n            // prop: dashPattern\r\n            // Array of line, space settings in pixels.\r\n            // Default is 8 pixel of line, 8 pixel of space.\r\n            // Note, limit to a 2 element array b/c of bug with higher order arrays.\r\n            dashPattern: [8,8]\r\n        };\r\n        $.extend(true, this.options, opts, options);\r\n\r\n        if (this.options.showTooltipPrecision < 0.01) {\r\n            this.options.showTooltipPrecision = 0.01;\r\n        }\r\n    }\r\n\r\n    DashedVerticalLine.prototype = new LineBase();\r\n    DashedVerticalLine.prototype.constructor = DashedVerticalLine;\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.addLine = function(opts) {\r\n        var line = new Line(opts);\r\n        line.uid = objCounter++;\r\n        this.objects.push(line);\r\n        this.objectNames.push(line.options.name);\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.addHorizontalLine = function(opts) {\r\n        var line = new HorizontalLine(opts);\r\n        line.uid = objCounter++;\r\n        this.objects.push(line);\r\n        this.objectNames.push(line.options.name);\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.addDashedHorizontalLine = function(opts) {\r\n        var line = new DashedHorizontalLine(opts);\r\n        line.uid = objCounter++;\r\n        this.objects.push(line);\r\n        this.objectNames.push(line.options.name);\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.addVerticalLine = function(opts) {\r\n        var line = new VerticalLine(opts);\r\n        line.uid = objCounter++;\r\n        this.objects.push(line);\r\n        this.objectNames.push(line.options.name);\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.addDashedVerticalLine = function(opts) {\r\n        var line = new DashedVerticalLine(opts);\r\n        line.uid = objCounter++;\r\n        this.objects.push(line);\r\n        this.objectNames.push(line.options.name);\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.addRectangle = function(opts) {\r\n        var line = new Rectangle(opts);\r\n        line.uid = objCounter++;\r\n        this.objects.push(line);\r\n        this.objectNames.push(line.options.name);\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.removeObject = function(idx) {\r\n        // check if integer, remove by index\r\n        if ($.type(idx) == 'number') {\r\n            this.objects.splice(idx, 1);\r\n            this.objectNames.splice(idx, 1);\r\n        }\r\n        // if string, remove by name\r\n        else {\r\n            var id = $.inArray(idx, this.objectNames);\r\n            if (id != -1) {\r\n                this.objects.splice(id, 1);\r\n                this.objectNames.splice(id, 1);\r\n            }\r\n        }\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.getObject = function(idx) {\r\n        // check if integer, remove by index\r\n        if ($.type(idx) == 'number') {\r\n            return this.objects[idx];\r\n        }\r\n        // if string, remove by name\r\n        else {\r\n            var id = $.inArray(idx, this.objectNames);\r\n            if (id != -1) {\r\n                return this.objects[id];\r\n            }\r\n        }\r\n    };\r\n    \r\n    // Set get as alias for getObject.\r\n    $.jqplot.CanvasOverlay.prototype.get = $.jqplot.CanvasOverlay.prototype.getObject;\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.clear = function(plot) {\r\n        this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());\r\n    };\r\n    \r\n    $.jqplot.CanvasOverlay.prototype.draw = function(plot) {\r\n        var obj, \r\n            objs = this.objects,\r\n            mr = this.markerRenderer,\r\n            start,\r\n            stop;\r\n        if (this.options.show) {\r\n            this.canvas._ctx.clearRect(0,0,this.canvas.getWidth(), this.canvas.getHeight());\r\n            for (var k=0; k<objs.length; k++) {\r\n                obj = objs[k];\r\n                var opts = $.extend(true, {}, obj.options);\r\n                if (obj.options.show) {\r\n                    // style and shadow properties should be set before\r\n                    // every draw of marker renderer.\r\n                    mr.shadow = obj.options.shadow;\r\n                    obj.tooltipWidthFactor = obj.options.lineWidth / obj.options.showTooltipPrecision;\r\n                    switch (obj.type) {\r\n                        case 'line':\r\n                            // style and shadow properties should be set before\r\n                            // every draw of marker renderer.\r\n                            mr.style = 'line';\r\n                            opts.closePath = false;\r\n                            start = [plot.axes[obj.options.xaxis].series_u2p(obj.options.start[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.start[1])];\r\n                            stop = [plot.axes[obj.options.xaxis].series_u2p(obj.options.stop[0]), plot.axes[obj.options.yaxis].series_u2p(obj.options.stop[1])];\r\n                            obj.gridStart = start;\r\n                            obj.gridStop = stop;\r\n                            mr.draw(start, stop, this.canvas._ctx, opts);\r\n                            break;\r\n                        case 'horizontalLine':\r\n                            \r\n                            // style and shadow properties should be set before\r\n                            // every draw of marker renderer.\r\n                            if (obj.options.y != null) {\r\n                                mr.style = 'line';\r\n                                opts.closePath = false;\r\n                                var xaxis = plot.axes[obj.options.xaxis],\r\n                                    xstart,\r\n                                    xstop,\r\n                                    y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),\r\n                                    xminoff = obj.options.xminOffset || obj.options.xOffset,\r\n                                    xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;\r\n                                if (obj.options.xmin != null) {\r\n                                    xstart = xaxis.series_u2p(obj.options.xmin);\r\n                                }\r\n                                else if (xminoff != null) {\r\n                                    if ($.type(xminoff) == \"number\") {\r\n                                        xstart = xaxis.series_u2p(xaxis.min + xminoff);\r\n                                    }\r\n                                    else if ($.type(xminoff) == \"string\") {\r\n                                        xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);\r\n                                    }\r\n                                }\r\n                                if (obj.options.xmax != null) {\r\n                                    xstop = xaxis.series_u2p(obj.options.xmax);\r\n                                }\r\n                                else if (xmaxoff != null) {\r\n                                    if ($.type(xmaxoff) == \"number\") {\r\n                                        xstop = xaxis.series_u2p(xaxis.max - xmaxoff);\r\n                                    }\r\n                                    else if ($.type(xmaxoff) == \"string\") {\r\n                                        xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);\r\n                                    }\r\n                                }\r\n                                if (xstop != null && xstart != null) {\r\n                                    obj.gridStart = [xstart, y];\r\n                                    obj.gridStop = [xstop, y];\r\n                                    mr.draw([xstart, y], [xstop, y], this.canvas._ctx, opts);\r\n                                }\r\n                            }\r\n                            break;\r\n\r\n                        case 'dashedHorizontalLine':\r\n                            \r\n                            var dashPat = obj.options.dashPattern;\r\n                            var dashPatLen = 0;\r\n                            for (var i=0; i<dashPat.length; i++) {\r\n                                dashPatLen += dashPat[i];\r\n                            }\r\n\r\n                            // style and shadow properties should be set before\r\n                            // every draw of marker renderer.\r\n                            if (obj.options.y != null) {\r\n                                mr.style = 'line';\r\n                                opts.closePath = false;\r\n                                var xaxis = plot.axes[obj.options.xaxis],\r\n                                    xstart,\r\n                                    xstop,\r\n                                    y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),\r\n                                    xminoff = obj.options.xminOffset || obj.options.xOffset,\r\n                                    xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;\r\n                                if (obj.options.xmin != null) {\r\n                                    xstart = xaxis.series_u2p(obj.options.xmin);\r\n                                }\r\n                                else if (xminoff != null) {\r\n                                    if ($.type(xminoff) == \"number\") {\r\n                                        xstart = xaxis.series_u2p(xaxis.min + xminoff);\r\n                                    }\r\n                                    else if ($.type(xminoff) == \"string\") {\r\n                                        xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);\r\n                                    }\r\n                                }\r\n                                if (obj.options.xmax != null) {\r\n                                    xstop = xaxis.series_u2p(obj.options.xmax);\r\n                                }\r\n                                else if (xmaxoff != null) {\r\n                                    if ($.type(xmaxoff) == \"number\") {\r\n                                        xstop = xaxis.series_u2p(xaxis.max - xmaxoff);\r\n                                    }\r\n                                    else if ($.type(xmaxoff) == \"string\") {\r\n                                        xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);\r\n                                    }\r\n                                }\r\n                                if (xstop != null && xstart != null) {\r\n                                    obj.gridStart = [xstart, y];\r\n                                    obj.gridStop = [xstop, y];\r\n                                    var numDash = Math.ceil((xstop - xstart)/dashPatLen);\r\n                                    var b=xstart, e;\r\n                                    for (var i=0; i<numDash; i++) {\r\n                                        for (var j=0; j<dashPat.length; j+=2) {\r\n                                            e = b+dashPat[j];\r\n                                            mr.draw([b, y], [e, y], this.canvas._ctx, opts);\r\n                                            b += dashPat[j];\r\n                                            if (j < dashPat.length-1) {\r\n                                                b += dashPat[j+1];\r\n                                            }\r\n                                        }\r\n                                    }\r\n                                }\r\n                            }\r\n                            break;\r\n\r\n                        case 'verticalLine':\r\n                            \r\n                            // style and shadow properties should be set before\r\n                            // every draw of marker renderer.\r\n                            if (obj.options.x != null) {\r\n                                mr.style = 'line';\r\n                                opts.closePath = false;\r\n                                var yaxis = plot.axes[obj.options.yaxis],\r\n                                    ystart,\r\n                                    ystop,\r\n                                    x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),\r\n                                    yminoff = obj.options.yminOffset || obj.options.yOffset,\r\n                                    ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;\r\n                                if (obj.options.ymin != null) {\r\n                                    ystart = yaxis.series_u2p(obj.options.ymin);\r\n                                }\r\n                                else if (yminoff != null) {\r\n                                    if ($.type(yminoff) == \"number\") {\r\n                                        ystart = yaxis.series_u2p(yaxis.min - yminoff);\r\n                                    }\r\n                                    else if ($.type(yminoff) == \"string\") {\r\n                                        ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);\r\n                                    }\r\n                                }\r\n                                if (obj.options.ymax != null) {\r\n                                    ystop = yaxis.series_u2p(obj.options.ymax);\r\n                                }\r\n                                else if (ymaxoff != null) {\r\n                                    if ($.type(ymaxoff) == \"number\") {\r\n                                        ystop = yaxis.series_u2p(yaxis.max + ymaxoff);\r\n                                    }\r\n                                    else if ($.type(ymaxoff) == \"string\") {\r\n                                        ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);\r\n                                    }\r\n                                }\r\n                                if (ystop != null && ystart != null) {\r\n                                    obj.gridStart = [x, ystart];\r\n                                    obj.gridStop = [x, ystop];\r\n                                    mr.draw([x, ystart], [x, ystop], this.canvas._ctx, opts);\r\n                                }\r\n                            }\r\n                            break;\r\n\r\n                        case 'dashedVerticalLine':\r\n                            \r\n                            var dashPat = obj.options.dashPattern;\r\n                            var dashPatLen = 0;\r\n                            for (var i=0; i<dashPat.length; i++) {\r\n                                dashPatLen += dashPat[i];\r\n                            }\r\n\r\n                            // style and shadow properties should be set before\r\n                            // every draw of marker renderer.\r\n                            if (obj.options.x != null) {\r\n                                mr.style = 'line';\r\n                                opts.closePath = false;\r\n                                var yaxis = plot.axes[obj.options.yaxis],\r\n                                    ystart,\r\n                                    ystop,\r\n                                    x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),\r\n                                    yminoff = obj.options.yminOffset || obj.options.yOffset,\r\n                                    ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;\r\n                                if (obj.options.ymin != null) {\r\n                                    ystart = yaxis.series_u2p(obj.options.ymin);\r\n                                }\r\n                                else if (yminoff != null) {\r\n                                    if ($.type(yminoff) == \"number\") {\r\n                                        ystart = yaxis.series_u2p(yaxis.min - yminoff);\r\n                                    }\r\n                                    else if ($.type(yminoff) == \"string\") {\r\n                                        ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);\r\n                                    }\r\n                                }\r\n                                if (obj.options.ymax != null) {\r\n                                    ystop = yaxis.series_u2p(obj.options.ymax);\r\n                                }\r\n                                else if (ymaxoff != null) {\r\n                                    if ($.type(ymaxoff) == \"number\") {\r\n                                        ystop = yaxis.series_u2p(yaxis.max + ymaxoff);\r\n                                    }\r\n                                    else if ($.type(ymaxoff) == \"string\") {\r\n                                        ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);\r\n                                    }\r\n                                }\r\n\r\n\r\n                                if (ystop != null && ystart != null) {\r\n                                    obj.gridStart = [x, ystart];\r\n                                    obj.gridStop = [x, ystop];\r\n                                    var numDash = Math.ceil((ystart - ystop)/dashPatLen);\r\n                                    var firstDashAdjust = ((numDash * dashPatLen) - (ystart - ystop))/2.0;\r\n                                    var b=ystart, e, bs, es;\r\n                                    for (var i=0; i<numDash; i++) {\r\n                                        for (var j=0; j<dashPat.length; j+=2) {\r\n                                            e = b - dashPat[j];\r\n                                            if (e < ystop) {\r\n                                                e = ystop;\r\n                                            }\r\n                                            if (b < ystop) {\r\n                                                b = ystop;\r\n                                            }\r\n                                            // es = e;\r\n                                            // if (i == 0) {\r\n                                            //  es += firstDashAdjust;\r\n                                            // }\r\n                                            mr.draw([x, b], [x, e], this.canvas._ctx, opts);\r\n                                            b -= dashPat[j];\r\n                                            if (j < dashPat.length-1) {\r\n                                                b -= dashPat[j+1];\r\n                                            }\r\n                                        }\r\n                                    }\r\n                                }\r\n                            }\r\n                            break;\r\n                            \r\n                        case 'rectangle':\r\n                            // style and shadow properties should be set before\r\n                            // every draw of marker renderer.\r\n                            mr.style = 'line';\r\n                            opts.closePath = true;\r\n                            \r\n                            var xaxis = plot.axes[obj.options.xaxis],\r\n                                    xstart,\r\n                                    xstop,\r\n                                    y = plot.axes[obj.options.yaxis].series_u2p(obj.options.y),\r\n                                    xminoff = obj.options.xminOffset || obj.options.xOffset,\r\n                                    xmaxoff = obj.options.xmaxOffset || obj.options.xOffset;\r\n                            if (obj.options.xmin != null) {\r\n                                xstart = xaxis.series_u2p(obj.options.xmin);\r\n                            }\r\n                            else if (xminoff != null) {\r\n                                if ($.type(xminoff) == \"number\") {\r\n                                    xstart = xaxis.series_u2p(xaxis.min + xminoff);\r\n                                }\r\n                                else if ($.type(xminoff) == \"string\") {\r\n                                    xstart = xaxis.series_u2p(xaxis.min) + parseFloat(xminoff);\r\n                                }\r\n                            }\r\n                            if (obj.options.xmax != null) {\r\n                                xstop = xaxis.series_u2p(obj.options.xmax);\r\n                            }\r\n                            else if (xmaxoff != null) {\r\n                                if ($.type(xmaxoff) == \"number\") {\r\n                                    xstop = xaxis.series_u2p(xaxis.max - xmaxoff);\r\n                                }\r\n                                else if ($.type(xmaxoff) == \"string\") {\r\n                                    xstop = xaxis.series_u2p(xaxis.max) - parseFloat(xmaxoff);\r\n                                }\r\n                            }\r\n                            \r\n                            var yaxis = plot.axes[obj.options.yaxis],\r\n                                ystart,\r\n                                ystop,\r\n                                x = plot.axes[obj.options.xaxis].series_u2p(obj.options.x),\r\n                                yminoff = obj.options.yminOffset || obj.options.yOffset,\r\n                                ymaxoff = obj.options.ymaxOffset || obj.options.yOffset;\r\n                            if (obj.options.ymin != null) {\r\n                                ystart = yaxis.series_u2p(obj.options.ymin);\r\n                            }\r\n                            else if (yminoff != null) {\r\n                                if ($.type(yminoff) == \"number\") {\r\n                                    ystart = yaxis.series_u2p(yaxis.min - yminoff);\r\n                                }\r\n                                else if ($.type(yminoff) == \"string\") {\r\n                                    ystart = yaxis.series_u2p(yaxis.min) - parseFloat(yminoff);\r\n                                }\r\n                            }\r\n                            if (obj.options.ymax != null) {\r\n                                ystop = yaxis.series_u2p(obj.options.ymax);\r\n                            }\r\n                            else if (ymaxoff != null) {\r\n                                if ($.type(ymaxoff) == \"number\") {\r\n                                    ystop = yaxis.series_u2p(yaxis.max + ymaxoff);\r\n                                }\r\n                                else if ($.type(ymaxoff) == \"string\") {\r\n                                    ystop = yaxis.series_u2p(yaxis.max) + parseFloat(ymaxoff);\r\n                                }\r\n                            }\r\n                            \r\n\r\n                            if (xstop != null && xstart != null && ystop != null && ystart != null) {\r\n                                obj.gridStart = [xstart, ystart];\r\n                                obj.gridStop = [xstop, ystop];\r\n                                \r\n                                this.canvas._ctx.fillStyle = obj.options.color;\r\n                                this.canvas._ctx.fillRect(xstart, ystart, xstop - xstart, ystop - ystart);\r\n                            }\r\n                            break;\r\n\r\n                        default:\r\n                            break;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    };\r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    $.jqplot.CanvasOverlay.postPlotDraw = function() {\r\n        var co = this.plugins.canvasOverlay;\r\n        // Memory Leaks patch    \r\n        if (co && co.highlightCanvas) {\r\n            co.highlightCanvas.resetCanvas();\r\n            co.highlightCanvas = null;\r\n        }\r\n        co.canvas = new $.jqplot.GenericCanvas();\r\n        \r\n        this.eventCanvas._elem.before(co.canvas.createElement(this._gridPadding, 'jqplot-overlayCanvas-canvas', this._plotDimensions, this));\r\n        co.canvas.setContext();\r\n        if (!co.deferDraw) {\r\n            co.draw(this);\r\n        }\r\n\r\n        var elem = document.createElement('div');\r\n        co._tooltipElem = $(elem);\r\n        elem = null;\r\n        co._tooltipElem.addClass('jqplot-canvasOverlay-tooltip');\r\n        co._tooltipElem.css({position:'absolute', display:'none'});\r\n        \r\n        this.eventCanvas._elem.before(co._tooltipElem);\r\n        this.eventCanvas._elem.bind('mouseleave', { elem: co._tooltipElem }, function (ev) { ev.data.elem.hide(); });\r\n\r\n        var co = null;\r\n    };\r\n\r\n\r\n    function showTooltip(plot, obj, gridpos, datapos) {\r\n        var co = plot.plugins.canvasOverlay;\r\n        var elem = co._tooltipElem;\r\n\r\n        var opts = obj.options, x, y;\r\n\r\n        elem.html($.jqplot.sprintf(opts.tooltipFormatString, datapos[0], datapos[1]));\r\n        \r\n        switch (opts.tooltipLocation) {\r\n            case 'nw':\r\n                x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;\r\n                y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);\r\n                break;\r\n            case 'n':\r\n                x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;\r\n                y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);\r\n                break;\r\n            case 'ne':\r\n                x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;\r\n                y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);\r\n                break;\r\n            case 'e':\r\n                x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;\r\n                y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;\r\n                break;\r\n            case 'se':\r\n                x = gridpos[0] + plot._gridPadding.left + opts.tooltipOffset;\r\n                y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;\r\n                break;\r\n            case 's':\r\n                x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true)/2;\r\n                y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;\r\n                break;\r\n            case 'sw':\r\n                x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;\r\n                y = gridpos[1] + plot._gridPadding.top + opts.tooltipOffset;\r\n                break;\r\n            case 'w':\r\n                x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;\r\n                y = gridpos[1] + plot._gridPadding.top - elem.outerHeight(true)/2;\r\n                break;\r\n            default: // same as 'nw'\r\n                x = gridpos[0] + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset;\r\n                y = gridpos[1] + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true);\r\n                break;\r\n        }\r\n\r\n        elem.css('left', x);\r\n        elem.css('top', y);\r\n        if (opts.fadeTooltip) {\r\n            // Fix for stacked up animations.  Thnanks Trevor!\r\n            elem.stop(true,true).fadeIn(opts.tooltipFadeSpeed);\r\n        }\r\n        else {\r\n            elem.show();\r\n        }\r\n        elem = null;\r\n    }\r\n\r\n\r\n    function isNearLine(point, lstart, lstop, width) {\r\n        // r is point to test, p and q are end points.\r\n        var rx = point[0];\r\n        var ry = point[1];\r\n        var px = Math.round(lstop[0]);\r\n        var py = Math.round(lstop[1]);\r\n        var qx = Math.round(lstart[0]);\r\n        var qy = Math.round(lstart[1]);\r\n\r\n        var l = Math.sqrt(Math.pow(px-qx, 2) + Math.pow(py-qy, 2));\r\n\r\n        // scale error term by length of line.\r\n        var eps = width*l;\r\n        var res = Math.abs((qx-px) * (ry-py) - (qy-py) * (rx-px));\r\n        var ret = (res < eps) ? true : false;\r\n        return ret;\r\n    }\r\n    \r\n    function isNearRectangle(point, lstart, lstop, width) {\r\n        // r is point to test, p and q are end points.\r\n        var rx = point[0];\r\n        var ry = point[1];\r\n        var px = Math.round(lstop[0]);\r\n        var py = Math.round(lstop[1]);\r\n        var qx = Math.round(lstart[0]);\r\n        var qy = Math.round(lstart[1]);\r\n        \r\n        var temp;\r\n        if (px > qx) { temp = px; px = qx; qx = temp; }\r\n        if (py > qy) { temp = py; py = qy; qy = temp; }\r\n        \r\n        var ret = (rx >= px && rx <= qx && ry >= py && ry <= qy);\r\n        \r\n        return ret;\r\n    }\r\n\r\n\r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        var co = plot.plugins.canvasOverlay;\r\n        var objs = co.objects;\r\n        var l = objs.length;\r\n        var obj, haveHighlight=false;\r\n        var elem;\r\n        for (var i=0; i<l; i++) {\r\n            obj = objs[i];\r\n            if (obj.options.showTooltip) {\r\n            \tvar n;\r\n                if (obj.type === 'rectangle') {\r\n                 n = isNearRectangle([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);\r\n                } else {\r\n                 n = isNearLine([gridpos.x, gridpos.y], obj.gridStart, obj.gridStop, obj.tooltipWidthFactor);\r\n                }\r\n                datapos = [plot.axes[obj.options.xaxis].series_p2u(gridpos.x), plot.axes[obj.options.yaxis].series_p2u(gridpos.y)];\r\n\r\n                // cases:\r\n                //    near line, no highlighting\r\n                //    near line, highliting on this line\r\n                //    near line, highlighting another line\r\n                //    not near any line, highlighting\r\n                //    not near any line, no highlighting\r\n\r\n                // near line, not currently highlighting\r\n                if (n && co.highlightObjectIndex == null) {\r\n                    switch (obj.type) {\r\n                        case 'line':\r\n                            showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);\r\n                            break;\r\n\r\n                        case 'horizontalLine':\r\n                        case 'dashedHorizontalLine':\r\n                            showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);\r\n                            break;\r\n\r\n                        case 'verticalLine':\r\n                        case 'dashedVerticalLine':\r\n                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);\r\n                            break;\r\n                            \r\n                        case 'rectangle':\r\n                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);\r\n                            break;\r\n                            \r\n                        default:\r\n                            break;\r\n                    } \r\n                    co.highlightObjectIndex = i;\r\n                    haveHighlight = true;\r\n                    break;\r\n                }\r\n\r\n                // near line, highlighting another line.\r\n                else if (n && co.highlightObjectIndex !== i) {\r\n                    // turn off tooltip.\r\n                    elem = co._tooltipElem;\r\n                    if (obj.fadeTooltip) {\r\n                        elem.fadeOut(obj.tooltipFadeSpeed);\r\n                    }\r\n                    else {\r\n                        elem.hide();\r\n                    }\r\n\r\n                    // turn on right tooltip.\r\n                    switch (obj.type) {\r\n                        case 'line':\r\n                            showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);\r\n                            break;\r\n\r\n                        case 'horizontalLine':\r\n                        case 'dashedHorizontalLine':\r\n                            showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);\r\n                            break;\r\n\r\n                        case 'verticalLine':\r\n                        case 'dashedVerticalLine':\r\n                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);\r\n                            break;\r\n                            \r\n                        case 'rectangle':\r\n                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);\r\n                            break;\r\n                            \r\n                        default:\r\n                            break;\r\n                    }\r\n\r\n                    co.highlightObjectIndex = i;\r\n                    haveHighlight = true;\r\n                    break;\r\n                }\r\n\r\n                // near line, already highlighting this line, update\r\n                else if (n) {\r\n                    switch (obj.type) {\r\n                        case 'line':\r\n                            showTooltip(plot, obj, [gridpos.x, gridpos.y], datapos);\r\n                            break;\r\n\r\n                        case 'horizontalLine':\r\n                        case 'dashedHorizontalLine':\r\n                            showTooltip(plot, obj, [gridpos.x, obj.gridStart[1]], [datapos[0], obj.options.y]);\r\n                            break;\r\n\r\n                        case 'verticalLine':\r\n                        case 'dashedVerticalLine':\r\n                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);\r\n                            break;\r\n                            \r\n                        case 'rectangle':\r\n                            showTooltip(plot, obj, [obj.gridStart[0], gridpos.y], [obj.options.x, datapos[1]]);\r\n                            break;\r\n                            \r\n                        default:\r\n                            break;\r\n                    }\r\n\r\n                    haveHighlight = true;\r\n                    break;\r\n                }\r\n            }\r\n        }\r\n\r\n        // check if we are highlighting and not near a line, turn it off.\r\n        if (!haveHighlight && co.highlightObjectIndex !== null) {\r\n            elem = co._tooltipElem;\r\n            obj = co.getObject(co.highlightObjectIndex);\r\n            if (obj.fadeTooltip) {\r\n                elem.fadeOut(obj.tooltipFadeSpeed);\r\n            }\r\n            else {\r\n                elem.hide();\r\n            }\r\n            co.highlightObjectIndex = null;\r\n        }\r\n    }\r\n    \r\n    $.jqplot.postInitHooks.push($.jqplot.CanvasOverlay.postPlotInit);\r\n    $.jqplot.postDrawHooks.push($.jqplot.CanvasOverlay.postPlotDraw);\r\n    $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);\r\n\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.canvasTextRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n *\r\n * included jsDate library by Chris Leonello:\r\n *\r\n * Copyright (c) 2010-2015 Chris Leonello\r\n *\r\n * jsDate is currently available for use in all personal or commercial projects \r\n * under both the MIT and GPL version 2.0 licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly.\r\n *\r\n * jsDate borrows many concepts and ideas from the Date Instance \r\n * Methods by Ken Snyder along with some parts of Ken's actual code.\r\n * \r\n * Ken's original Date Instance Methods and copyright notice:\r\n * \r\n * Ken Snyder (ken d snyder at gmail dot com)\r\n * 2008-09-10\r\n * version 2.0.2 (http://kendsnyder.com/sandbox/date/)     \r\n * Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/)\r\n *\r\n * jqplotToImage function based on Larry Siden's export-jqplot-to-png.js.\r\n * Larry has generously given permission to adapt his code for inclusion\r\n * into jqPlot.\r\n *\r\n * Larry's original code can be found here:\r\n *\r\n * https://github.com/lsiden/export-jqplot-to-png\r\n * \r\n * \r\n */\r\n\r\n(function($) {    \r\n    // This code is a modified version of the canvastext.js code, copyright below:\r\n    //\r\n    // This code is released to the public domain by Jim Studt, 2007.\r\n    // He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/\r\n    //\r\n    $.jqplot.CanvasTextRenderer = function(options){\r\n        this.fontStyle = 'normal';  // normal, italic, oblique [not implemented]\r\n        this.fontVariant = 'normal';    // normal, small caps [not implemented]\r\n        this.fontWeight = 'normal'; // normal, bold, bolder, lighter, 100 - 900\r\n        this.fontSize = '10px'; \r\n        this.fontFamily = 'sans-serif';\r\n        this.fontStretch = 1.0;\r\n        this.fillStyle = '#666666';\r\n        this.angle = 0;\r\n        this.textAlign = 'start';\r\n        this.textBaseline = 'alphabetic';\r\n        this.text;\r\n        this.width;\r\n        this.height;\r\n        this.pt2px = 1.28;\r\n\r\n        $.extend(true, this, options);\r\n        this.normalizedFontSize = this.normalizeFontSize(this.fontSize);\r\n        this.setHeight();\r\n    };\r\n    \r\n    $.jqplot.CanvasTextRenderer.prototype.init = function(options) {\r\n        $.extend(true, this, options);\r\n        this.normalizedFontSize = this.normalizeFontSize(this.fontSize);\r\n        this.setHeight();\r\n    };\r\n    \r\n    // convert css spec into point size\r\n    // returns float\r\n    $.jqplot.CanvasTextRenderer.prototype.normalizeFontSize = function(sz) {\r\n        sz = String(sz);\r\n        var n = parseFloat(sz);\r\n        if (sz.indexOf('px') > -1) {\r\n            return n/this.pt2px;\r\n        }\r\n        else if (sz.indexOf('pt') > -1) {\r\n            return n;\r\n        }\r\n        else if (sz.indexOf('em') > -1) {\r\n            return n*12;\r\n        }\r\n        else if (sz.indexOf('%') > -1) {\r\n            return n*12/100;\r\n        }\r\n        // default to pixels;\r\n        else {\r\n            return n/this.pt2px;\r\n        }\r\n    };\r\n    \r\n    \r\n    $.jqplot.CanvasTextRenderer.prototype.fontWeight2Float = function(w) {\r\n        // w = normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900\r\n        // return values adjusted for Hershey font.\r\n        if (Number(w)) {\r\n            return w/400;\r\n        }\r\n        else {\r\n            switch (w) {\r\n                case 'normal':\r\n                    return 1;\r\n                    break;\r\n                case 'bold':\r\n                    return 1.75;\r\n                    break;\r\n                case 'bolder':\r\n                    return 2.25;\r\n                    break;\r\n                case 'lighter':\r\n                    return 0.75;\r\n                    break;\r\n                default:\r\n                    return 1;\r\n                    break;\r\n             }   \r\n        }\r\n    };\r\n    \r\n    $.jqplot.CanvasTextRenderer.prototype.getText = function() {\r\n        return this.text;\r\n    };\r\n    \r\n    $.jqplot.CanvasTextRenderer.prototype.setText = function(t, ctx) {\r\n        this.text = t;\r\n        this.setWidth(ctx);\r\n        return this;\r\n    };\r\n    \r\n    $.jqplot.CanvasTextRenderer.prototype.getWidth = function(ctx) {\r\n        return this.width;\r\n    };\r\n    \r\n    $.jqplot.CanvasTextRenderer.prototype.setWidth = function(ctx, w) {\r\n        if (!w) {\r\n            this.width = this.measure(ctx, this.text);\r\n        }\r\n        else {\r\n            this.width = w;   \r\n        }\r\n        return this;\r\n    };\r\n    \r\n    // return height in pixels.\r\n    $.jqplot.CanvasTextRenderer.prototype.getHeight = function(ctx) {\r\n        return this.height;\r\n    };\r\n    \r\n    // w - height in pt\r\n    // set heigh in px\r\n    $.jqplot.CanvasTextRenderer.prototype.setHeight = function(w) {\r\n        if (!w) {\r\n            //height = this.fontSize /0.75;\r\n            this.height = this.normalizedFontSize * this.pt2px;\r\n        }\r\n        else {\r\n            this.height = w;   \r\n        }\r\n        return this;\r\n    };\r\n\r\n    $.jqplot.CanvasTextRenderer.prototype.letter = function (ch)\r\n    {\r\n        return this.letters[ch];\r\n    };\r\n\r\n    $.jqplot.CanvasTextRenderer.prototype.ascent = function()\r\n    {\r\n        return this.normalizedFontSize;\r\n    };\r\n\r\n    $.jqplot.CanvasTextRenderer.prototype.descent = function()\r\n    {\r\n        return 7.0*this.normalizedFontSize/25.0;\r\n    };\r\n\r\n    $.jqplot.CanvasTextRenderer.prototype.measure = function(ctx, str)\r\n    {\r\n        var total = 0;\r\n        var len = str.length;\r\n \r\n        for (var i = 0; i < len; i++) {\r\n            var c = this.letter(str.charAt(i));\r\n            if (c) {\r\n                total += c.width * this.normalizedFontSize / 25.0 * this.fontStretch;\r\n            }\r\n        }\r\n        return total;\r\n    };\r\n\r\n    $.jqplot.CanvasTextRenderer.prototype.draw = function(ctx,str)\r\n    {\r\n        var x = 0;\r\n        // leave room at bottom for descenders.\r\n        var y = this.height*0.72;\r\n         var total = 0;\r\n         var len = str.length;\r\n         var mag = this.normalizedFontSize / 25.0;\r\n\r\n         ctx.save();\r\n         var tx, ty;\r\n         \r\n         // 1st quadrant\r\n         if ((-Math.PI/2 <= this.angle && this.angle <= 0) || (Math.PI*3/2 <= this.angle && this.angle <= Math.PI*2)) {\r\n             tx = 0;\r\n             ty = -Math.sin(this.angle) * this.width;\r\n         }\r\n         // 4th quadrant\r\n         else if ((0 < this.angle && this.angle <= Math.PI/2) || (-Math.PI*2 <= this.angle && this.angle <= -Math.PI*3/2)) {\r\n             tx = Math.sin(this.angle) * this.height;\r\n             ty = 0;\r\n         }\r\n         // 2nd quadrant\r\n         else if ((-Math.PI < this.angle && this.angle < -Math.PI/2) || (Math.PI <= this.angle && this.angle <= Math.PI*3/2)) {\r\n             tx = -Math.cos(this.angle) * this.width;\r\n             ty = -Math.sin(this.angle) * this.width - Math.cos(this.angle) * this.height;\r\n         }\r\n         // 3rd quadrant\r\n         else if ((-Math.PI*3/2 < this.angle && this.angle < Math.PI) || (Math.PI/2 < this.angle && this.angle < Math.PI)) {\r\n             tx = Math.sin(this.angle) * this.height - Math.cos(this.angle)*this.width;\r\n             ty = -Math.cos(this.angle) * this.height;\r\n         }\r\n         \r\n         ctx.strokeStyle = this.fillStyle;\r\n         ctx.fillStyle = this.fillStyle;\r\n         ctx.translate(tx, ty);\r\n         ctx.rotate(this.angle);\r\n         ctx.lineCap = \"round\";\r\n         // multiplier was 2.0\r\n         var fact = (this.normalizedFontSize > 30) ? 2.0 : 2 + (30 - this.normalizedFontSize)/20;\r\n         ctx.lineWidth = fact * mag * this.fontWeight2Float(this.fontWeight);\r\n         \r\n         for ( var i = 0; i < len; i++) {\r\n            var c = this.letter( str.charAt(i));\r\n            if ( !c) {\r\n                continue;\r\n            }\r\n\r\n            ctx.beginPath();\r\n\r\n            var penUp = 1;\r\n            var needStroke = 0;\r\n            for ( var j = 0; j < c.points.length; j++) {\r\n              var a = c.points[j];\r\n              if ( a[0] == -1 && a[1] == -1) {\r\n                  penUp = 1;\r\n                  continue;\r\n              }\r\n              if ( penUp) {\r\n                  ctx.moveTo( x + a[0]*mag*this.fontStretch, y - a[1]*mag);\r\n                  penUp = false;\r\n              } else {\r\n                  ctx.lineTo( x + a[0]*mag*this.fontStretch, y - a[1]*mag);\r\n              }\r\n            }\r\n            ctx.stroke();\r\n            x += c.width*mag*this.fontStretch;\r\n         }\r\n         ctx.restore();\r\n         return total;\r\n    };\r\n\r\n    $.jqplot.CanvasTextRenderer.prototype.letters = {\r\n         ' ': { width: 16, points: [] },\r\n         '!': { width: 10, points: [[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] },\r\n         '\"': { width: 16, points: [[4,21],[4,14],[-1,-1],[12,21],[12,14]] },\r\n         '#': { width: 21, points: [[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]] },\r\n         '$': { width: 20, points: [[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },\r\n         '%': { width: 24, points: [[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] },\r\n         '&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] },\r\n         '\\'': { width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] },\r\n         '(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] },\r\n         ')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] },\r\n         '*': { width: 16, points: [[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]] },\r\n         '+': { width: 26, points: [[13,18],[13,0],[-1,-1],[4,9],[22,9]] },\r\n         ',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },\r\n         '-': { width: 18, points: [[6,9],[12,9]] },\r\n         '.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] },\r\n         '/': { width: 22, points: [[20,25],[2,-7]] },\r\n         '0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] },\r\n         '1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] },\r\n         '2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] },\r\n         '3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },\r\n         '4': { width: 20, points: [[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]] },\r\n         '5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },\r\n         '6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] },\r\n         '7': { width: 20, points: [[17,21],[7,0],[-1,-1],[3,21],[17,21]] },\r\n         '8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] },\r\n         '9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] },\r\n         ':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] },\r\n         ';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },\r\n         '<': { width: 24, points: [[20,18],[4,9],[20,0]] },\r\n         '=': { width: 26, points: [[4,12],[22,12],[-1,-1],[4,6],[22,6]] },\r\n         '>': { width: 24, points: [[4,18],[20,9],[4,0]] },\r\n         '?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]] },\r\n         '@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]] },\r\n         'A': { width: 18, points: [[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]] },\r\n         'B': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] },\r\n         'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] },\r\n         'D': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] },\r\n         'E': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]] },\r\n         'F': { width: 18, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]] },\r\n         'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]] },\r\n         'H': { width: 22, points: [[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]] },\r\n         'I': { width: 8, points: [[4,21],[4,0]] },\r\n         'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] },\r\n         'K': { width: 21, points: [[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]] },\r\n         'L': { width: 17, points: [[4,21],[4,0],[-1,-1],[4,0],[16,0]] },\r\n         'M': { width: 24, points: [[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]] },\r\n         'N': { width: 22, points: [[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]] },\r\n         'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] },\r\n         'P': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] },\r\n         'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]] },\r\n         'R': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]] },\r\n         'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },\r\n         'T': { width: 16, points: [[8,21],[8,0],[-1,-1],[1,21],[15,21]] },\r\n         'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] },\r\n         'V': { width: 18, points: [[1,21],[9,0],[-1,-1],[17,21],[9,0]] },\r\n         'W': { width: 24, points: [[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]] },\r\n         'X': { width: 20, points: [[3,21],[17,0],[-1,-1],[17,21],[3,0]] },\r\n         'Y': { width: 18, points: [[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]] },\r\n         'Z': { width: 20, points: [[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]] },\r\n         '[': { width: 14, points: [[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]] },\r\n         '\\\\': { width: 14, points: [[0,21],[14,-3]] },\r\n         ']': { width: 14, points: [[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]] },\r\n         '^': { width: 16, points: [[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]] },\r\n         '_': { width: 16, points: [[0,-2],[16,-2]] },\r\n         '`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] },\r\n         'a': { width: 19, points: [[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },\r\n         'b': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },\r\n         'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },\r\n         'd': { width: 19, points: [[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },\r\n         'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },\r\n         'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]] },\r\n         'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },\r\n         'h': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },\r\n         'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]] },\r\n         'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] },\r\n         'k': { width: 17, points: [[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]] },\r\n         'l': { width: 8, points: [[4,21],[4,0]] },\r\n         'm': { width: 30, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] },\r\n         'n': { width: 19, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },\r\n         'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] },\r\n         'p': { width: 19, points: [[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },\r\n         'q': { width: 19, points: [[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },\r\n         'r': { width: 13, points: [[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]] },\r\n         's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] },\r\n         't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]] },\r\n         'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]] },\r\n         'v': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0]] },\r\n         'w': { width: 22, points: [[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]] },\r\n         'x': { width: 17, points: [[3,14],[14,0],[-1,-1],[14,14],[3,0]] },\r\n         'y': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] },\r\n         'z': { width: 17, points: [[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]] },\r\n         '{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] },\r\n         '|': { width: 8, points: [[4,25],[4,-7]] },\r\n         '}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] },\r\n         '~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] }\r\n     };\r\n     \r\n    $.jqplot.CanvasFontRenderer = function(options) {\r\n        options = options || {};\r\n        if (!options.pt2px) {\r\n            options.pt2px = 1.5;\r\n        }\r\n        $.jqplot.CanvasTextRenderer.call(this, options);\r\n    };\r\n    \r\n    $.jqplot.CanvasFontRenderer.prototype = new $.jqplot.CanvasTextRenderer({});\r\n    $.jqplot.CanvasFontRenderer.prototype.constructor = $.jqplot.CanvasFontRenderer;\r\n\r\n    $.jqplot.CanvasFontRenderer.prototype.measure = function(ctx, str)\r\n    {\r\n        // var fstyle = this.fontStyle+' '+this.fontVariant+' '+this.fontWeight+' '+this.fontSize+' '+this.fontFamily;\r\n        var fstyle = this.fontSize+' '+this.fontFamily;\r\n        ctx.save();\r\n        ctx.font = fstyle;\r\n        var w = ctx.measureText(str).width;\r\n        ctx.restore();\r\n        return w;\r\n    };\r\n\r\n    $.jqplot.CanvasFontRenderer.prototype.draw = function(ctx, str)\r\n    {\r\n        var x = 0;\r\n        // leave room at bottom for descenders.\r\n        var y = this.height*0.72;\r\n        //var y = 12;\r\n\r\n         ctx.save();\r\n         var tx, ty;\r\n         \r\n         // 1st quadrant\r\n         if ((-Math.PI/2 <= this.angle && this.angle <= 0) || (Math.PI*3/2 <= this.angle && this.angle <= Math.PI*2)) {\r\n             tx = 0;\r\n             ty = -Math.sin(this.angle) * this.width;\r\n         }\r\n         // 4th quadrant\r\n         else if ((0 < this.angle && this.angle <= Math.PI/2) || (-Math.PI*2 <= this.angle && this.angle <= -Math.PI*3/2)) {\r\n             tx = Math.sin(this.angle) * this.height;\r\n             ty = 0;\r\n         }\r\n         // 2nd quadrant\r\n         else if ((-Math.PI < this.angle && this.angle < -Math.PI/2) || (Math.PI <= this.angle && this.angle <= Math.PI*3/2)) {\r\n             tx = -Math.cos(this.angle) * this.width;\r\n             ty = -Math.sin(this.angle) * this.width - Math.cos(this.angle) * this.height;\r\n         }\r\n         // 3rd quadrant\r\n         else if ((-Math.PI*3/2 < this.angle && this.angle < Math.PI) || (Math.PI/2 < this.angle && this.angle < Math.PI)) {\r\n             tx = Math.sin(this.angle) * this.height - Math.cos(this.angle)*this.width;\r\n             ty = -Math.cos(this.angle) * this.height;\r\n         }\r\n         ctx.strokeStyle = this.fillStyle;\r\n         ctx.fillStyle = this.fillStyle;\r\n        // var fstyle = this.fontStyle+' '+this.fontVariant+' '+this.fontWeight+' '+this.fontSize+' '+this.fontFamily;\r\n        var fstyle = this.fontSize+' '+this.fontFamily;\r\n         ctx.font = fstyle;\r\n         ctx.translate(tx, ty);\r\n         ctx.rotate(this.angle);\r\n         ctx.fillText(str, x, y);\r\n         // ctx.strokeText(str, x, y);\r\n\r\n         ctx.restore();\r\n    };\r\n    \r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.categoryAxisRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {   \r\n    /**\r\n    *  class: $.jqplot.CategoryAxisRenderer\r\n    *  A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series.\r\n    *  \r\n    *  To use this renderer, include the plugin in your source\r\n    *  > <script type=\"text/javascript\" language=\"javascript\" src=\"plugins/jqplot.categoryAxisRenderer.js\"></script>\r\n    *  \r\n    *  and supply the appropriate options to your plot\r\n    *  \r\n    *  > {axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}}\r\n    **/\r\n    $.jqplot.CategoryAxisRenderer = function(options) {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n        // prop: sortMergedLabels\r\n        // True to sort tick labels when labels are created by merging\r\n        // x axis values from multiple series.  That is, say you have\r\n        // two series like:\r\n        // > line1 = [[2006, 4],            [2008, 9], [2009, 16]];\r\n        // > line2 = [[2006, 3], [2007, 7], [2008, 6]];\r\n        // If no label array is specified, tick labels will be collected\r\n        // from the x values of the series.  With sortMergedLabels\r\n        // set to true, tick labels will be:\r\n        // > [2006, 2007, 2008, 2009]\r\n        // With sortMergedLabels set to false, tick labels will be:\r\n        // > [2006, 2008, 2009, 2007]\r\n        //\r\n        // Note, this property is specified on the renderOptions for the \r\n        // axes when creating a plot:\r\n        // > axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer, rendererOptions:{sortMergedLabels:true}}}\r\n        this.sortMergedLabels = false;\r\n    };\r\n    \r\n    $.jqplot.CategoryAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.CategoryAxisRenderer.prototype.constructor = $.jqplot.CategoryAxisRenderer;\r\n    \r\n    $.jqplot.CategoryAxisRenderer.prototype.init = function(options){\r\n        this.groups = 1;\r\n        this.groupLabels = [];\r\n        this._groupLabels = [];\r\n        this._grouped = false;\r\n        this._barsPerGroup = null;\r\n        this.reverse = false;\r\n        // prop: tickRenderer\r\n        // A class of a rendering engine for creating the ticks labels displayed on the plot, \r\n        // See <$.jqplot.AxisTickRenderer>.\r\n        // this.tickRenderer = $.jqplot.AxisTickRenderer;\r\n        // this.labelRenderer = $.jqplot.AxisLabelRenderer;\r\n        $.extend(true, this, {tickOptions:{formatString:'%d'}}, options);\r\n        var db = this._dataBounds;\r\n        // Go through all the series attached to this axis and find\r\n        // the min/max bounds for this axis.\r\n        for (var i=0; i<this._series.length; i++) {\r\n            var s = this._series[i];\r\n            if (s.groups) {\r\n                this.groups = s.groups;\r\n            }\r\n            var d = s.data;\r\n            \r\n            for (var j=0; j<d.length; j++) { \r\n                if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                    if (d[j][0] < db.min || db.min == null) {\r\n                        db.min = d[j][0];\r\n                    }\r\n                    if (d[j][0] > db.max || db.max == null) {\r\n                        db.max = d[j][0];\r\n                    }\r\n                }              \r\n                else {\r\n                    if (d[j][1] < db.min || db.min == null) {\r\n                        db.min = d[j][1];\r\n                    }\r\n                    if (d[j][1] > db.max || db.max == null) {\r\n                        db.max = d[j][1];\r\n                    }\r\n                }              \r\n            }\r\n        }\r\n        \r\n        if (this.groupLabels.length) {\r\n            this.groups = this.groupLabels.length;\r\n        }\r\n    };\r\n \r\n\r\n    $.jqplot.CategoryAxisRenderer.prototype.createTicks = function() {\r\n        // we're are operating on an axis here\r\n        var ticks = this._ticks;\r\n        var userTicks = this.ticks;\r\n        var name = this.name;\r\n        // databounds were set on axis initialization.\r\n        var db = this._dataBounds;\r\n        var dim, interval;\r\n        var min, max;\r\n        var pos1, pos2;\r\n        var tt, i;\r\n\r\n        // if we already have ticks, use them.\r\n        if (userTicks.length) {\r\n            // adjust with blanks if we have groups\r\n            if (this.groups > 1 && !this._grouped) {\r\n                var l = userTicks.length;\r\n                var skip = parseInt(l/this.groups, 10);\r\n                var count = 0;\r\n                for (var i=skip; i<l; i+=skip) {\r\n                    userTicks.splice(i+count, 0, ' ');\r\n                    count++;\r\n                }\r\n                this._grouped = true;\r\n            }\r\n            this.min = 0.5;\r\n            this.max = userTicks.length + 0.5;\r\n            var range = this.max - this.min;\r\n            this.numberTicks = 2*userTicks.length + 1;\r\n            for (i=0; i<userTicks.length; i++){\r\n                tt = this.min + 2 * i * range / (this.numberTicks-1);\r\n                // need a marker before and after the tick\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                t.showLabel = false;\r\n                // t.showMark = true;\r\n                t.setTick(tt, this.name);\r\n                this._ticks.push(t);\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                t.label = userTicks[i];\r\n                // t.showLabel = true;\r\n                t.showMark = false;\r\n                t.showGridline = false;\r\n                t.setTick(tt+0.5, this.name);\r\n                this._ticks.push(t);\r\n            }\r\n            // now add the last tick at the end\r\n            var t = new this.tickRenderer(this.tickOptions);\r\n            t.showLabel = false;\r\n            // t.showMark = true;\r\n            t.setTick(tt+1, this.name);\r\n            this._ticks.push(t);\r\n        }\r\n\r\n        // we don't have any ticks yet, let's make some!\r\n        else {\r\n            if (name == 'xaxis' || name == 'x2axis') {\r\n                dim = this._plotDimensions.width;\r\n            }\r\n            else {\r\n                dim = this._plotDimensions.height;\r\n            }\r\n            \r\n            // if min, max and number of ticks specified, user can't specify interval.\r\n            if (this.min != null && this.max != null && this.numberTicks != null) {\r\n                this.tickInterval = null;\r\n            }\r\n            \r\n            // if max, min, and interval specified and interval won't fit, ignore interval.\r\n            if (this.min != null && this.max != null && this.tickInterval != null) {\r\n                if (parseInt((this.max-this.min)/this.tickInterval, 10) != (this.max-this.min)/this.tickInterval) {\r\n                    this.tickInterval = null;\r\n                }\r\n            }\r\n        \r\n            // find out how many categories are in the lines and collect labels\r\n            var labels = [];\r\n            var numcats = 0;\r\n            var min = 0.5;\r\n            var max, val;\r\n            var isMerged = false;\r\n            for (var i=0; i<this._series.length; i++) {\r\n                var s = this._series[i];\r\n                for (var j=0; j<s.data.length; j++) {\r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        val = s.data[j][0];\r\n                    }\r\n                    else {\r\n                        val = s.data[j][1];\r\n                    }\r\n                    if ($.inArray(val, labels) == -1) {\r\n                        isMerged = true;\r\n                        numcats += 1;      \r\n                        labels.push(val);\r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (isMerged && this.sortMergedLabels) {\r\n                if (typeof labels[0] == \"string\") {\r\n                    labels.sort();\r\n                } else {\r\n                    labels.sort(function(a,b) { return a - b; });\r\n                }\r\n            }\r\n            \r\n            // keep a reference to these tick labels to use for redrawing plot (see bug #57)\r\n            this.ticks = labels;\r\n            \r\n            // now bin the data values to the right lables.\r\n            for (var i=0; i<this._series.length; i++) {\r\n                var s = this._series[i];\r\n                for (var j=0; j<s.data.length; j++) {\r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        val = s.data[j][0];\r\n                    }\r\n                    else {\r\n                        val = s.data[j][1];\r\n                    }\r\n                    // for category axis, force the values into category bins.\r\n                    // we should have the value in the label array now.\r\n                    var idx = $.inArray(val, labels)+1;\r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        s.data[j][0] = idx;\r\n                    }\r\n                    else {\r\n                        s.data[j][1] = idx;\r\n                    }\r\n                }\r\n            }\r\n            \r\n            // adjust with blanks if we have groups\r\n            if (this.groups > 1 && !this._grouped) {\r\n                var l = labels.length;\r\n                var skip = parseInt(l/this.groups, 10);\r\n                var count = 0;\r\n                for (var i=skip; i<l; i+=skip+1) {\r\n                    labels[i] = ' ';\r\n                }\r\n                this._grouped = true;\r\n            }\r\n        \r\n            max = numcats + 0.5;\r\n            if (this.numberTicks == null) {\r\n                this.numberTicks = 2*numcats + 1;\r\n            }\r\n\r\n            var range = max - min;\r\n            this.min = min;\r\n            this.max = max;\r\n            var track = 0;\r\n            \r\n            // todo: adjust this so more ticks displayed.\r\n            var maxVisibleTicks = parseInt(3+dim/10, 10);\r\n            var skip = parseInt(numcats/maxVisibleTicks, 10);\r\n\r\n            if (this.tickInterval == null) {\r\n\r\n                this.tickInterval = range / (this.numberTicks-1);\r\n\r\n            }\r\n            // if tickInterval is specified, we will ignore any computed maximum.\r\n            for (var i=0; i<this.numberTicks; i++){\r\n                tt = this.min + i * this.tickInterval;\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                // if even tick, it isn't a category, it's a divider\r\n                if (i/2 == parseInt(i/2, 10)) {\r\n                    t.showLabel = false;\r\n                    t.showMark = true;\r\n                }\r\n                else {\r\n                    if (skip>0 && track<skip) {\r\n                        t.showLabel = false;\r\n                        track += 1;\r\n                    }\r\n                    else {\r\n                        t.showLabel = true;\r\n                        track = 0;\r\n                    } \r\n                    t.label = t.formatter(t.formatString, labels[(i-1)/2]);\r\n                    t.showMark = false;\r\n                    t.showGridline = false;\r\n                }\r\n                t.setTick(tt, this.name);\r\n                this._ticks.push(t);\r\n            }\r\n        }\r\n        \r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.CategoryAxisRenderer.prototype.draw = function(ctx, plot) {\r\n        if (this.show) {\r\n            // populate the axis label and value properties.\r\n            // createTicks is a method on the renderer, but\r\n            // call it within the scope of the axis.\r\n            this.renderer.createTicks.call(this);\r\n            // fill a div with axes labels in the right direction.\r\n            // Need to pregenerate each axis to get its bounds and\r\n            // position it and the labels correctly on the plot.\r\n            var dim=0;\r\n            var temp;\r\n            // Added for theming.\r\n            if (this._elem) {\r\n                // this._elem.empty();\r\n                // Memory Leaks patch\r\n                this._elem.emptyForce();\r\n            }\r\n\r\n            this._elem = this._elem || $('<div class=\"jqplot-axis jqplot-'+this.name+'\" style=\"position:absolute;\"></div>');\r\n            \r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                this._elem.width(this._plotDimensions.width);\r\n            }\r\n            else {\r\n                this._elem.height(this._plotDimensions.height);\r\n            }\r\n            \r\n            // create a _label object.\r\n            this.labelOptions.axis = this.name;\r\n            this._label = new this.labelRenderer(this.labelOptions);\r\n            if (this._label.show) {\r\n                var elem = this._label.draw(ctx, plot);\r\n                elem.appendTo(this._elem);\r\n            }\r\n    \r\n            var t = this._ticks;\r\n            for (var i=0; i<t.length; i++) {\r\n                var tick = t[i];\r\n                if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) {\r\n                    var elem = tick.draw(ctx, plot);\r\n                    elem.appendTo(this._elem);\r\n                }\r\n            }\r\n        \r\n            this._groupLabels = [];\r\n            // now make group labels\r\n            for (var i=0; i<this.groupLabels.length; i++)\r\n            {\r\n                var elem = $('<div style=\"position:absolute;\" class=\"jqplot-'+this.name+'-groupLabel\"></div>');\r\n                elem.html(this.groupLabels[i]);\r\n                this._groupLabels.push(elem);\r\n                elem.appendTo(this._elem);\r\n            }\r\n        }\r\n        return this._elem;\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.CategoryAxisRenderer.prototype.set = function() { \r\n        var dim = 0;\r\n        var temp;\r\n        var w = 0;\r\n        var h = 0;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        if (this.show) {\r\n            var t = this._ticks;\r\n            for (var i=0; i<t.length; i++) {\r\n                var tick = t[i];\r\n                if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) {\r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        temp = tick._elem.outerHeight(true);\r\n                    }\r\n                    else {\r\n                        temp = tick._elem.outerWidth(true);\r\n                    }\r\n                    if (temp > dim) {\r\n                        dim = temp;\r\n                    }\r\n                }\r\n            }\r\n            \r\n            var dim2 = 0;\r\n            for (var i=0; i<this._groupLabels.length; i++) {\r\n                var l = this._groupLabels[i];\r\n                if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                    temp = l.outerHeight(true);\r\n                }\r\n                else {\r\n                    temp = l.outerWidth(true);\r\n                }\r\n                if (temp > dim2) {\r\n                    dim2 = temp;\r\n                }\r\n            }\r\n            \r\n            if (lshow) {\r\n                w = this._label._elem.outerWidth(true);\r\n                h = this._label._elem.outerHeight(true); \r\n            }\r\n            if (this.name == 'xaxis') {\r\n                dim += dim2 + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'});\r\n            }\r\n            else if (this.name == 'x2axis') {\r\n                dim += dim2 + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', top:'0px'});\r\n            }\r\n            else if (this.name == 'yaxis') {\r\n                dim += dim2 + w;\r\n                this._elem.css({'width':dim+'px', left:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n            else {\r\n                dim += dim2 + w;\r\n                this._elem.css({'width':dim+'px', right:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n        }  \r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.CategoryAxisRenderer.prototype.pack = function(pos, offsets) {\r\n        var ticks = this._ticks;\r\n        var max = this.max;\r\n        var min = this.min;\r\n        var offmax = offsets.max;\r\n        var offmin = offsets.min;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        var i;\r\n\r\n        for (var p in pos) {\r\n            this._elem.css(p, pos[p]);\r\n        }\r\n        \r\n        this._offsets = offsets;\r\n        // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left.\r\n        var pixellength = offmax - offmin;\r\n        var unitlength = max - min;\r\n        \r\n        if (!this.reverse) {\r\n            // point to unit and unit to point conversions references to Plot DOM element top left corner.\r\n            \r\n            this.u2p = function(u){\r\n                return (u - min) * pixellength / unitlength + offmin;\r\n            };\r\n\r\n            this.p2u = function(p){\r\n                return (p - offmin) * unitlength / pixellength + min;\r\n            };\r\n                    \r\n            if (this.name == 'xaxis' || this.name == 'x2axis'){\r\n                this.series_u2p = function(u){\r\n                    return (u - min) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + min;\r\n                };\r\n            }\r\n            \r\n            else {\r\n                this.series_u2p = function(u){\r\n                    return (u - max) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + max;\r\n                };\r\n            }\r\n        }\r\n\r\n        else {\r\n            // point to unit and unit to point conversions references to Plot DOM element top left corner.\r\n            \r\n            this.u2p = function(u){\r\n                return offmin + (max - u) * pixellength / unitlength;\r\n            };\r\n\r\n            this.p2u = function(p){\r\n                return min + (p - offmin) * unitlength / pixellength;\r\n            };\r\n                    \r\n            if (this.name == 'xaxis' || this.name == 'x2axis'){\r\n                this.series_u2p = function(u){\r\n                    return (max - u) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + max;\r\n                };\r\n            }\r\n            \r\n            else {\r\n                this.series_u2p = function(u){\r\n                    return (min - u) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + min;\r\n                };\r\n            }\r\n\r\n        }\r\n            \r\n        \r\n        if (this.show) {\r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                for (i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {\r\n                        var shim;\r\n                        \r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'xaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    // position at start\r\n                                    else {\r\n                                        shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'end':\r\n                                    shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'start':\r\n                                    shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'middle':\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getWidth()/2;\r\n                        }\r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('left', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                \r\n                var labeledge=['bottom', 0];\r\n                if (lshow) {\r\n                    var w = this._label._elem.outerWidth(true);\r\n                    this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px');\r\n                    if (this.name == 'xaxis') {\r\n                        this._label._elem.css('bottom', '0px');\r\n                        labeledge = ['bottom', this._label._elem.outerHeight(true)];\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('top', '0px');\r\n                        labeledge = ['top', this._label._elem.outerHeight(true)];\r\n                    }\r\n                    this._label.pack();\r\n                }\r\n                \r\n                // draw the group labels\r\n                var step = parseInt(this._ticks.length/this.groups, 10) + 1;\r\n                for (i=0; i<this._groupLabels.length; i++) {\r\n                    var mid = 0;\r\n                    var count = 0;\r\n                    for (var j=i*step; j<(i+1)*step; j++) {\r\n                        if (j >= this._ticks.length-1) continue; // the last tick does not exist as there is no other group in order to have an empty one.\r\n                        if (this._ticks[j]._elem && this._ticks[j].label != \" \") {\r\n                            var t = this._ticks[j]._elem;\r\n                            var p = t.position();\r\n                            mid += p.left + t.outerWidth(true)/2;\r\n                            count++;\r\n                        }\r\n                    }\r\n                    mid = mid/count;\r\n                    this._groupLabels[i].css({'left':(mid - this._groupLabels[i].outerWidth(true)/2)});\r\n                    this._groupLabels[i].css(labeledge[0], labeledge[1]);\r\n                }\r\n            }\r\n            else {\r\n                for (i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {                        \r\n                        var shim;\r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'yaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                case 'end':\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'start':\r\n                                    if (t.angle > 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'middle':\r\n                                    // if (t.angle > 0) {\r\n                                    //     shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    // else {\r\n                                    //     shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getHeight()/2;\r\n                        }\r\n                        \r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('top', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                \r\n                var labeledge=['left', 0];\r\n                if (lshow) {\r\n                    var h = this._label._elem.outerHeight(true);\r\n                    this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px');\r\n                    if (this.name == 'yaxis') {\r\n                        this._label._elem.css('left', '0px');\r\n                        labeledge = ['left', this._label._elem.outerWidth(true)];\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('right', '0px');\r\n                        labeledge = ['right', this._label._elem.outerWidth(true)];\r\n                    }   \r\n                    this._label.pack();\r\n                }\r\n                \r\n                // draw the group labels, position top here, do left after label position.\r\n                var step = parseInt(this._ticks.length/this.groups, 10) + 1; // step is one more than before as we don't want to have overlaps in loops\r\n                for (i=0; i<this._groupLabels.length; i++) {\r\n                    var mid = 0;\r\n                    var count = 0;\r\n                    for (var j=i*step; j<(i+1)*step; j++) { // j must never reach (i+1)*step as we don't want to have overlap between loops\r\n                        if (j >= this._ticks.length-1) continue; // the last tick does not exist as there is no other group in order to have an empty one.\r\n                        if (this._ticks[j]._elem && this._ticks[j].label != \" \") {\r\n                            var t = this._ticks[j]._elem;\r\n                            var p = t.position();\r\n                            mid += p.top + t.outerHeight()/2;\r\n                            count++;\r\n                        }\r\n                    }\r\n                    mid = mid/count;\r\n                    this._groupLabels[i].css({'top':mid - this._groupLabels[i].outerHeight()/2});\r\n                    this._groupLabels[i].css(labeledge[0], labeledge[1]);\r\n                    \r\n                }\r\n            }\r\n        }\r\n    };    \r\n    \r\n    \r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.ciParser.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.ciParser\r\n     * Data Renderer function which converts a custom JSON data object into jqPlot data format.\r\n     * Set this as a callable on the jqplot dataRenderer plot option:\r\n     * \r\n     * > plot = $.jqplot('mychart', [data], { dataRenderer: $.jqplot.ciParser, ... });\r\n     * \r\n     * Where data is an object in JSON format or a JSON encoded string conforming to the\r\n     * City Index API spec.\r\n     * \r\n     * Note that calling the renderer function is handled internally by jqPlot.  The\r\n     * user does not have to call the function.  The parameters described below will\r\n     * automatically be passed to the ciParser function.\r\n     * \r\n     * Parameters:\r\n     * data - JSON encoded string or object.\r\n     * plot - reference to jqPlot Plot object.\r\n     * \r\n     * Returns:\r\n     * data array in jqPlot format.\r\n     * \r\n     */\r\n    $.jqplot.ciParser = function (data, plot) {\r\n        var ret = [],\r\n            line,\r\n            temp,\r\n            i, j, k, kk;\r\n    \r\n         if (typeof(data) == \"string\") {\r\n             data =  $.jqplot.JSON.parse(data, handleStrings);\r\n         }\r\n \r\n         else if (typeof(data) == \"object\") {\r\n             for (k in data) {\r\n                 for (i=0; i<data[k].length; i++) {\r\n                     for (kk in data[k][i]) {\r\n                         data[k][i][kk] = handleStrings(kk, data[k][i][kk]);\r\n                     }\r\n                 }\r\n             }\r\n         }\r\n \r\n         else {\r\n             return null;\r\n         }\r\n \r\n         // function handleStrings\r\n         // Checks any JSON encoded strings to see if they are\r\n         // encoded dates.  If so, pull out the timestamp.\r\n         // Expects dates to be represented by js timestamps.\r\n \r\n         function handleStrings(key, value) {\r\n            var a;\r\n            if (value != null) {\r\n                if (value.toString().indexOf('Date') >= 0) {\r\n                    //here we will try to extract the ticks from the Date string in the \"value\" fields of JSON returned data\r\n                    a = /^\\/Date\\((-?[0-9]+)\\)\\/$/.exec(value);\r\n                    if (a) {\r\n                        return parseInt(a[1], 10);\r\n                    }\r\n                }\r\n                return value;\r\n            }\r\n         }\r\n \r\n        for (var prop in data) {\r\n            line = [];\r\n            temp = data[prop];\r\n            switch (prop) {\r\n                case \"PriceTicks\":\r\n                    for (i=0; i<temp.length; i++) {\r\n                        line.push([temp[i]['TickDate'], temp[i]['Price']]);\r\n                    }\r\n                    break;\r\n                case \"PriceBars\":\r\n                    for (i=0; i<temp.length; i++) {\r\n                        line.push([temp[i]['BarDate'], temp[i]['Open'], temp[i]['High'], temp[i]['Low'], temp[i]['Close']]);\r\n                    }\r\n                    break;\r\n            }\r\n            ret.push(line);\r\n        }\r\n        return ret;\r\n    };\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.cursor.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    \r\n    /**\r\n     * Class: $.jqplot.Cursor\r\n     * Plugin class representing the cursor as displayed on the plot.\r\n     */\r\n    $.jqplot.Cursor = function(options) {\r\n        // Group: Properties\r\n        //\r\n        // prop: style\r\n        // CSS spec for cursor style\r\n        this.style = 'crosshair';\r\n        this.previousCursor = 'auto';\r\n        // prop: show\r\n        // whether to show the cursor or not.\r\n        this.show = $.jqplot.config.enablePlugins;\r\n        // prop: showTooltip\r\n        // show a cursor position tooltip.  Location of the tooltip\r\n        // will be controlled by followMouse and tooltipLocation.\r\n        this.showTooltip = true;\r\n        // prop: followMouse\r\n        // Tooltip follows the mouse, it is not at a fixed location.\r\n        // Tooltip will show on the grid at the location given by\r\n        // tooltipLocation, offset from the grid edge by tooltipOffset.\r\n        this.followMouse = false;\r\n        // prop: tooltipLocation\r\n        // Where to position tooltip.  If followMouse is true, this is\r\n        // relative to the cursor, otherwise, it is relative to the grid.\r\n        // One of 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'\r\n        this.tooltipLocation = 'se';\r\n        // prop: tooltipOffset\r\n        // Pixel offset of tooltip from the grid boudaries or cursor center.\r\n        this.tooltipOffset = 6;\r\n        // prop: showTooltipGridPosition\r\n        // show the grid pixel coordinates of the mouse.\r\n        this.showTooltipGridPosition = false;\r\n        // prop: showTooltipUnitPosition\r\n        // show the unit (data) coordinates of the mouse.\r\n        this.showTooltipUnitPosition = true;\r\n        // prop: showTooltipDataPosition\r\n        // Used with showVerticalLine to show intersecting data points in the tooltip.\r\n        this.showTooltipDataPosition = false;\r\n        // prop: tooltipFormatString\r\n        // sprintf format string for the tooltip.\r\n        // Uses Ash Searle's javascript sprintf implementation\r\n        // found here: http://hexmen.com/blog/2007/03/printf-sprintf/\r\n        // See http://perldoc.perl.org/functions/sprintf.html for reference\r\n        // Note, if showTooltipDataPosition is true, the default tooltipFormatString\r\n        // will be set to the cursorLegendFormatString, not the default given here.\r\n        this.tooltipFormatString = '%.4P, %.4P';\r\n        // prop: useAxesFormatters\r\n        // Use the x and y axes formatters to format the text in the tooltip.\r\n        this.useAxesFormatters = true;\r\n        // prop: tooltipAxisGroups\r\n        // Show position for the specified axes.\r\n        // This is an array like [['xaxis', 'yaxis'], ['xaxis', 'y2axis']]\r\n        // Default is to compute automatically for all visible axes.\r\n        this.tooltipAxisGroups = [];\r\n        // prop: zoom\r\n        // Enable plot zooming.\r\n        this.zoom = false;\r\n        // zoomProxy and zoomTarget properties are not directly set by user.  \r\n        // They Will be set through call to zoomProxy method.\r\n        this.zoomProxy = false;\r\n        this.zoomTarget = false;\r\n        // prop: looseZoom\r\n        // Will expand zoom range to provide more rounded tick values.\r\n        // Works only with linear, log and date axes.\r\n        this.looseZoom = true;\r\n        // prop: clickReset\r\n        // Will reset plot zoom if single click on plot without drag.\r\n        this.clickReset = false;\r\n        // prop: dblClickReset\r\n        // Will reset plot zoom if double click on plot without drag.\r\n        this.dblClickReset = true;\r\n        // prop: showVerticalLine\r\n        // draw a vertical line across the plot which follows the cursor.\r\n        // When the line is near a data point, a special legend and/or tooltip can\r\n        // be updated with the data values.\r\n        this.showVerticalLine = false;\r\n        // prop: showHorizontalLine\r\n        // draw a horizontal line across the plot which follows the cursor.\r\n        this.showHorizontalLine = false;\r\n        // prop: constrainZoomTo\r\n        // 'none', 'x' or 'y'\r\n        this.constrainZoomTo = 'none';\r\n        // // prop: autoscaleConstraint\r\n        // // when a constrained axis is specified, true will\r\n        // // auatoscale the adjacent axis.\r\n        // this.autoscaleConstraint = true;\r\n        this.shapeRenderer = new $.jqplot.ShapeRenderer();\r\n        this._zoom = {start:[], end:[], started: false, zooming:false, isZoomed:false, axes:{start:{}, end:{}}, gridpos:{}, datapos:{}};\r\n        this._tooltipElem;\r\n        this.zoomCanvas;\r\n        this.cursorCanvas;\r\n        // prop: intersectionThreshold\r\n        // pixel distance from data point or marker to consider cursor lines intersecting with point.\r\n        // If data point markers are not shown, this should be >= 1 or will often miss point intersections.\r\n        this.intersectionThreshold = 2;\r\n        // prop: showCursorLegend\r\n        // Replace the plot legend with an enhanced legend displaying intersection information.\r\n        this.showCursorLegend = false;\r\n        // prop: cursorLegendFormatString\r\n        // Format string used in the cursor legend.  If showTooltipDataPosition is true,\r\n        // this will also be the default format string used by tooltipFormatString.\r\n        this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString;\r\n        // whether the cursor is over the grid or not.\r\n        this._oldHandlers = {onselectstart: null, ondrag: null, onmousedown: null};\r\n        // prop: constrainOutsideZoom\r\n        // True to limit actual zoom area to edges of grid, even when zooming\r\n        // outside of plot area.  That is, can't zoom out by mousing outside plot.\r\n        this.constrainOutsideZoom = true;\r\n        // prop: showTooltipOutsideZoom\r\n        // True will keep updating the tooltip when zooming of the grid.\r\n        this.showTooltipOutsideZoom = false;\r\n        // true if mouse is over grid, false if not.\r\n        this.onGrid = false;\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    $.jqplot.Cursor.cursorLegendFormatString = '%s x:%s, y:%s';\r\n    \r\n    // called with scope of plot\r\n    $.jqplot.Cursor.init = function (target, data, opts){\r\n        // add a cursor attribute to the plot\r\n        var options = opts || {};\r\n        this.plugins.cursor = new $.jqplot.Cursor(options.cursor);\r\n        var c = this.plugins.cursor;\r\n\r\n        if (c.show) {\r\n            $.jqplot.eventListenerHooks.push(['jqplotMouseEnter', handleMouseEnter]);\r\n            $.jqplot.eventListenerHooks.push(['jqplotMouseLeave', handleMouseLeave]);\r\n            $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMouseMove]);\r\n            \r\n            if (c.showCursorLegend) {              \r\n                opts.legend = opts.legend || {};\r\n                opts.legend.renderer =  $.jqplot.CursorLegendRenderer;\r\n                opts.legend.formatString = this.plugins.cursor.cursorLegendFormatString;\r\n                opts.legend.show = true;\r\n            }\r\n            \r\n            if (c.zoom) {\r\n                $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleMouseDown]);\r\n                \r\n                if (c.clickReset) {\r\n                    $.jqplot.eventListenerHooks.push(['jqplotClick', handleClick]);\r\n                }\r\n                \r\n                if (c.dblClickReset) {\r\n                    $.jqplot.eventListenerHooks.push(['jqplotDblClick', handleDblClick]);\r\n                }             \r\n            }\r\n    \r\n            this.resetZoom = function() {\r\n                var axes = this.axes;\r\n                if (!c.zoomProxy) {\r\n                    for (var ax in axes) {\r\n                        axes[ax].reset();\r\n                        axes[ax]._ticks = [];\r\n                        // fake out tick creation algorithm to make sure original auto\r\n                        // computed format string is used if _overrideFormatString is true\r\n                        if (c._zoom.axes[ax] !== undefined) {\r\n                            axes[ax]._autoFormatString = c._zoom.axes[ax].tickFormatString;\r\n                        }\r\n                    }\r\n                    this.redraw();\r\n                }\r\n                else {\r\n                    var ctx = this.plugins.cursor.zoomCanvas._ctx;\r\n                    ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n                    ctx = null;\r\n                }\r\n                this.plugins.cursor._zoom.isZoomed = false;\r\n                this.target.trigger('jqplotResetZoom', [this, this.plugins.cursor]);\r\n            };\r\n            \r\n\r\n            if (c.showTooltipDataPosition) {\r\n                c.showTooltipUnitPosition = false;\r\n                c.showTooltipGridPosition = false;\r\n                if (options.cursor.tooltipFormatString == undefined) {\r\n                    c.tooltipFormatString = $.jqplot.Cursor.cursorLegendFormatString;\r\n                }\r\n            }\r\n        }\r\n    };\r\n    \r\n    // called with context of plot\r\n    $.jqplot.Cursor.postDraw = function() {\r\n        var c = this.plugins.cursor;\r\n        \r\n        // Memory Leaks patch\r\n        if (c.zoomCanvas) {\r\n            c.zoomCanvas.resetCanvas();\r\n            c.zoomCanvas = null;\r\n        }\r\n        \r\n        if (c.cursorCanvas) {\r\n            c.cursorCanvas.resetCanvas();\r\n            c.cursorCanvas = null;\r\n        }\r\n        \r\n        if (c._tooltipElem) {\r\n            c._tooltipElem.emptyForce();\r\n            c._tooltipElem = null;\r\n        }\r\n\r\n        \r\n        if (c.zoom) {\r\n            c.zoomCanvas = new $.jqplot.GenericCanvas();\r\n            this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions, this));\r\n            c.zoomCanvas.setContext();\r\n        }\r\n\r\n        var elem = document.createElement('div');\r\n        c._tooltipElem = $(elem);\r\n        elem = null;\r\n        c._tooltipElem.addClass('jqplot-cursor-tooltip');\r\n        c._tooltipElem.css({position:'absolute', display:'none'});\r\n        \r\n        \r\n        if (c.zoomCanvas) {\r\n            c.zoomCanvas._elem.before(c._tooltipElem);\r\n        }\r\n\r\n        else {\r\n            this.eventCanvas._elem.before(c._tooltipElem);\r\n        }\r\n\r\n        if (c.showVerticalLine || c.showHorizontalLine) {\r\n            c.cursorCanvas = new $.jqplot.GenericCanvas();\r\n            this.eventCanvas._elem.before(c.cursorCanvas.createElement(this._gridPadding, 'jqplot-cursor-canvas', this._plotDimensions, this));\r\n            c.cursorCanvas.setContext();\r\n        }\r\n\r\n        // if we are showing the positions in unit coordinates, and no axes groups\r\n        // were specified, create a default set.\r\n        if (c.showTooltipUnitPosition){\r\n            if (c.tooltipAxisGroups.length === 0) {\r\n                var series = this.series;\r\n                var s;\r\n                var temp = [];\r\n                for (var i=0; i<series.length; i++) {\r\n                    s = series[i];\r\n                    var ax = s.xaxis+','+s.yaxis;\r\n                    if ($.inArray(ax, temp) == -1) {\r\n                        temp.push(ax);\r\n                    }\r\n                }\r\n                for (var i=0; i<temp.length; i++) {\r\n                    c.tooltipAxisGroups.push(temp[i].split(','));\r\n                }\r\n            }\r\n        }\r\n    };\r\n    \r\n    // Group: methods\r\n    //\r\n    // method: $.jqplot.Cursor.zoomProxy\r\n    // links targetPlot to controllerPlot so that plot zooming of\r\n    // targetPlot will be controlled by zooming on the controllerPlot.\r\n    // controllerPlot will not actually zoom, but acts as an\r\n    // overview plot.  Note, the zoom options must be set to true for\r\n    // zoomProxy to work.\r\n    $.jqplot.Cursor.zoomProxy = function(targetPlot, controllerPlot) {\r\n        var tc = targetPlot.plugins.cursor;\r\n        var cc = controllerPlot.plugins.cursor;\r\n        tc.zoomTarget = true;\r\n        tc.zoom = true;\r\n        tc.style = 'auto';\r\n        tc.dblClickReset = false;\r\n        cc.zoom = true;\r\n        cc.zoomProxy = true;\r\n              \r\n        controllerPlot.target.bind('jqplotZoom', plotZoom);\r\n        controllerPlot.target.bind('jqplotResetZoom', plotReset);\r\n\r\n        function plotZoom(ev, gridpos, datapos, plot, cursor) {\r\n            tc.doZoom(gridpos, datapos, targetPlot, cursor);\r\n        } \r\n\r\n        function plotReset(ev, plot, cursor) {\r\n            targetPlot.resetZoom();\r\n        }\r\n    };\r\n    \r\n    $.jqplot.Cursor.prototype.resetZoom = function(plot, cursor) {\r\n        var axes = plot.axes;\r\n        var cax = cursor._zoom.axes;\r\n        if (!plot.plugins.cursor.zoomProxy && cursor._zoom.isZoomed) {\r\n            for (var ax in axes) {\r\n                // axes[ax]._ticks = [];\r\n                // axes[ax].min = cax[ax].min;\r\n                // axes[ax].max = cax[ax].max;\r\n                // axes[ax].numberTicks = cax[ax].numberTicks; \r\n                // axes[ax].tickInterval = cax[ax].tickInterval;\r\n                // // for date axes\r\n                // axes[ax].daTickInterval = cax[ax].daTickInterval;\r\n                axes[ax].reset();\r\n                axes[ax]._ticks = [];\r\n                // fake out tick creation algorithm to make sure original auto\r\n                // computed format string is used if _overrideFormatString is true\r\n                axes[ax]._autoFormatString = cax[ax].tickFormatString;\r\n            }\r\n            plot.redraw();\r\n            cursor._zoom.isZoomed = false;\r\n        }\r\n        else {\r\n            var ctx = cursor.zoomCanvas._ctx;\r\n            ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n            ctx = null;\r\n        }\r\n        plot.target.trigger('jqplotResetZoom', [plot, cursor]);\r\n    };\r\n    \r\n    $.jqplot.Cursor.resetZoom = function(plot) {\r\n        plot.resetZoom();\r\n    };\r\n    \r\n    $.jqplot.Cursor.prototype.doZoom = function (gridpos, datapos, plot, cursor) {\r\n        var c = cursor;\r\n        var axes = plot.axes;\r\n        var zaxes = c._zoom.axes;\r\n        var start = zaxes.start;\r\n        var end = zaxes.end;\r\n        var min, max, dp, span,\r\n            newmin, newmax, curax, _numberTicks, ret;\r\n        var ctx = plot.plugins.cursor.zoomCanvas._ctx;\r\n        // don't zoom if zoom area is too small (in pixels)\r\n        if ((c.constrainZoomTo == 'none' && Math.abs(gridpos.x - c._zoom.start[0]) > 6 && Math.abs(gridpos.y - c._zoom.start[1]) > 6) || (c.constrainZoomTo == 'x' && Math.abs(gridpos.x - c._zoom.start[0]) > 6) ||  (c.constrainZoomTo == 'y' && Math.abs(gridpos.y - c._zoom.start[1]) > 6)) {\r\n            if (!plot.plugins.cursor.zoomProxy) {\r\n                for (var ax in datapos) {\r\n                    // make a copy of the original axes to revert back.\r\n                    if (c._zoom.axes[ax] == undefined) {\r\n                        c._zoom.axes[ax] = {};\r\n                        c._zoom.axes[ax].numberTicks = axes[ax].numberTicks;\r\n                        c._zoom.axes[ax].tickInterval = axes[ax].tickInterval;\r\n                        // for date axes...\r\n                        c._zoom.axes[ax].daTickInterval = axes[ax].daTickInterval;\r\n                        c._zoom.axes[ax].min = axes[ax].min;\r\n                        c._zoom.axes[ax].max = axes[ax].max;\r\n                        c._zoom.axes[ax].tickFormatString = (axes[ax].tickOptions != null) ? axes[ax].tickOptions.formatString :  '';\r\n                    }\r\n\r\n\r\n                    if ((c.constrainZoomTo == 'none') || (c.constrainZoomTo == 'x' && ax.charAt(0) == 'x') || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'y')) {   \r\n                        dp = datapos[ax];\r\n                        if (dp != null) {           \r\n                            if (dp > start[ax]) { \r\n                                newmin = start[ax];\r\n                                newmax = dp;\r\n                            }\r\n                            else {\r\n                                span = start[ax] - dp;\r\n                                newmin = dp;\r\n                                newmax = start[ax];\r\n                            }\r\n\r\n                            curax = axes[ax];\r\n\r\n                            _numberTicks = null;\r\n\r\n                            // if aligning this axis, use number of ticks from previous axis.\r\n                            // Do I need to reset somehow if alignTicks is changed and then graph is replotted??\r\n                            if (curax.alignTicks) {\r\n                                if (curax.name === 'x2axis' && plot.axes.xaxis.show) {\r\n                                    _numberTicks = plot.axes.xaxis.numberTicks;\r\n                                }\r\n                                else if (curax.name.charAt(0) === 'y' && curax.name !== 'yaxis' && curax.name !== 'yMidAxis' && plot.axes.yaxis.show) {\r\n                                    _numberTicks = plot.axes.yaxis.numberTicks;\r\n                                }\r\n                            }\r\n                            \r\n                            if (this.looseZoom && (axes[ax].renderer.constructor === $.jqplot.LinearAxisRenderer || axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer )) { //} || axes[ax].renderer.constructor === $.jqplot.DateAxisRenderer)) {\r\n\r\n                                ret = $.jqplot.LinearTickGenerator(newmin, newmax, curax._scalefact, _numberTicks);\r\n\r\n                                // if new minimum is less than \"true\" minimum of axis display, adjust it\r\n                                if (axes[ax].tickInset && ret[0] < axes[ax].min + axes[ax].tickInset * axes[ax].tickInterval) {\r\n                                    ret[0] += ret[4];\r\n                                    ret[2] -= 1;\r\n                                }\r\n\r\n                                // if new maximum is greater than \"true\" max of axis display, adjust it\r\n                                if (axes[ax].tickInset && ret[1] > axes[ax].max - axes[ax].tickInset * axes[ax].tickInterval) {\r\n                                    ret[1] -= ret[4];\r\n                                    ret[2] -= 1;\r\n                                }\r\n\r\n                                // for log axes, don't fall below current minimum, this will look bad and can't have 0 in range anyway.\r\n                                if (axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer && ret[0] < axes[ax].min) {\r\n                                    // remove a tick and shift min up\r\n                                    ret[0] += ret[4];\r\n                                    ret[2] -= 1;\r\n                                }\r\n\r\n                                axes[ax].min = ret[0];\r\n                                axes[ax].max = ret[1];\r\n                                axes[ax]._autoFormatString = ret[3];\r\n                                axes[ax].numberTicks = ret[2];\r\n                                axes[ax].tickInterval = ret[4];\r\n                                // for date axes...\r\n                                axes[ax].daTickInterval = [ret[4]/1000, 'seconds'];\r\n                            }\r\n                            else {\r\n                                axes[ax].min = newmin;\r\n                                axes[ax].max = newmax;\r\n                                axes[ax].tickInterval = null;\r\n                                axes[ax].numberTicks = null;\r\n                                // for date axes...\r\n                                axes[ax].daTickInterval = null;\r\n                            }\r\n\r\n                            axes[ax]._ticks = [];\r\n                        }\r\n                    }\r\n                            \r\n                    // if ((c.constrainZoomTo == 'x' && ax.charAt(0) == 'y' && c.autoscaleConstraint) || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'x' && c.autoscaleConstraint)) {\r\n                    //     dp = datapos[ax];\r\n                    //     if (dp != null) {\r\n                    //         axes[ax].max == null;\r\n                    //         axes[ax].min = null;\r\n                    //     }\r\n                    // }\r\n                }\r\n                ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n                plot.redraw();\r\n                c._zoom.isZoomed = true;\r\n                ctx = null;\r\n            }\r\n            plot.target.trigger('jqplotZoom', [gridpos, datapos, plot, cursor]);\r\n        }\r\n    };\r\n    \r\n    $.jqplot.preInitHooks.push($.jqplot.Cursor.init);\r\n    $.jqplot.postDrawHooks.push($.jqplot.Cursor.postDraw);\r\n    \r\n    function updateTooltip(gridpos, datapos, plot) {\r\n        var c = plot.plugins.cursor;\r\n        var s = '';\r\n        var addbr = false;\r\n        if (c.showTooltipGridPosition) {\r\n            s = gridpos.x+', '+gridpos.y;\r\n            addbr = true;\r\n        }\r\n        if (c.showTooltipUnitPosition) {\r\n            var g;\r\n            for (var i=0; i<c.tooltipAxisGroups.length; i++) {\r\n                g = c.tooltipAxisGroups[i];\r\n                if (addbr) {\r\n                    s += '<br />';\r\n                }\r\n                if (c.useAxesFormatters) {\r\n                    for (var j=0; j<g.length; j++) {\r\n                        if (j) {\r\n                            s += ', ';\r\n                        }\r\n                        var af = plot.axes[g[j]]._ticks[0].formatter;\r\n                        var afstr = plot.axes[g[j]]._ticks[0].formatString;\r\n                        s += af(afstr, datapos[g[j]]);\r\n                    }\r\n                }\r\n                else {\r\n                    s += $.jqplot.sprintf(c.tooltipFormatString, datapos[g[0]], datapos[g[1]]);\r\n                }\r\n                addbr = true;\r\n            }\r\n        }\r\n        \r\n        if (c.showTooltipDataPosition) {\r\n            var series = plot.series; \r\n            var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);\r\n            var addbr = false;\r\n        \r\n            for (var i = 0; i< series.length; i++) {\r\n                if (series[i].show) {\r\n                    var idx = series[i].index;\r\n                    var label = series[i].label.toString();\r\n                    var cellid = $.inArray(idx, ret.indices);\r\n                    var sx = undefined;\r\n                    var sy = undefined;\r\n                    if (cellid != -1) {\r\n                        var data = ret.data[cellid].data;\r\n                        if (c.useAxesFormatters) {\r\n                            var xf = series[i]._xaxis._ticks[0].formatter;\r\n                            var yf = series[i]._yaxis._ticks[0].formatter;\r\n                            var xfstr = series[i]._xaxis._ticks[0].formatString;\r\n                            var yfstr = series[i]._yaxis._ticks[0].formatString;\r\n                            sx = xf(xfstr, data[0]);\r\n                            sy = yf(yfstr, data[1]);\r\n                        }\r\n                        else {\r\n                            sx = data[0];\r\n                            sy = data[1];\r\n                        }\r\n                        if (addbr) {\r\n                            s += '<br />';\r\n                        }\r\n                        s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy);\r\n                        addbr = true;\r\n                    }\r\n                }\r\n            }\r\n            \r\n        }\r\n        c._tooltipElem.html(s);\r\n    }\r\n    \r\n    function moveLine(gridpos, plot) {\r\n        var c = plot.plugins.cursor;\r\n        var ctx = c.cursorCanvas._ctx;\r\n        ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n        if (c.showVerticalLine) {\r\n            c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]);\r\n        }\r\n        if (c.showHorizontalLine) {\r\n            c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]);\r\n        }\r\n        var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y);\r\n        if (c.showCursorLegend) {\r\n            var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');\r\n            for (var i=0; i<cells.length; i++) {\r\n                var idx = $(cells[i]).data('seriesIndex');\r\n                var series = plot.series[idx];\r\n                var label = series.label.toString();\r\n                var cellid = $.inArray(idx, ret.indices);\r\n                var sx = undefined;\r\n                var sy = undefined;\r\n                if (cellid != -1) {\r\n                    var data = ret.data[cellid].data;\r\n                    if (c.useAxesFormatters) {\r\n                        var xf = series._xaxis._ticks[0].formatter;\r\n                        var yf = series._yaxis._ticks[0].formatter;\r\n                        var xfstr = series._xaxis._ticks[0].formatString;\r\n                        var yfstr = series._yaxis._ticks[0].formatString;\r\n                        sx = xf(xfstr, data[0]);\r\n                        sy = yf(yfstr, data[1]);\r\n                    }\r\n                    else {\r\n                        sx = data[0];\r\n                        sy = data[1];\r\n                    }\r\n                }\r\n                if (plot.legend.escapeHtml) {\r\n                    $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));\r\n                }\r\n                else {\r\n                    $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy));\r\n                }\r\n            }        \r\n        }\r\n        ctx = null;\r\n    }\r\n        \r\n    function getIntersectingPoints(plot, x, y) {\r\n        var ret = {indices:[], data:[]};\r\n        var s, i, d0, d, j, r, p;\r\n        var threshold;\r\n        var c = plot.plugins.cursor;\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            s = plot.series[i];\r\n            r = s.renderer;\r\n            if (s.show) {\r\n                threshold = c.intersectionThreshold;\r\n                if (s.showMarker) {\r\n                    threshold += s.markerRenderer.size/2;\r\n                }\r\n                for (var j=0; j<s.gridData.length; j++) {\r\n                    p = s.gridData[j];\r\n                    // check vertical line\r\n                    if (c.showVerticalLine) {\r\n                        if (Math.abs(x-p[0]) <= threshold) {\r\n                            ret.indices.push(i);\r\n                            ret.data.push({seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]});\r\n                        }\r\n                    }\r\n                } \r\n            }\r\n        }\r\n        return ret;\r\n    }\r\n    \r\n    function moveTooltip(gridpos, plot) {\r\n        var c = plot.plugins.cursor;  \r\n        var elem = c._tooltipElem;\r\n        switch (c.tooltipLocation) {\r\n            case 'nw':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;\r\n                var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);\r\n                break;\r\n            case 'n':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;\r\n                var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);\r\n                break;\r\n            case 'ne':\r\n                var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;\r\n                var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true);\r\n                break;\r\n            case 'e':\r\n                var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;\r\n                var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;\r\n                break;\r\n            case 'se':\r\n                var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;\r\n                var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;\r\n                break;\r\n            case 's':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;\r\n                var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;\r\n                break;\r\n            case 'sw':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;\r\n                var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;\r\n                break;\r\n            case 'w':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset;\r\n                var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;\r\n                break;\r\n            default:\r\n                var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset;\r\n                var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset;\r\n                break;\r\n        }\r\n            \r\n        elem.css('left', x);\r\n        elem.css('top', y);\r\n        elem = null;\r\n    }\r\n    \r\n    function positionTooltip(plot) { \r\n        // fake a grid for positioning\r\n        var grid = plot._gridPadding; \r\n        var c = plot.plugins.cursor;\r\n        var elem = c._tooltipElem;  \r\n        switch (c.tooltipLocation) {\r\n            case 'nw':\r\n                var a = grid.left + c.tooltipOffset;\r\n                var b = grid.top + c.tooltipOffset;\r\n                elem.css('left', a);\r\n                elem.css('top', b);\r\n                break;\r\n            case 'n':\r\n                var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;\r\n                var b = grid.top + c.tooltipOffset;\r\n                elem.css('left', a);\r\n                elem.css('top', b);\r\n                break;\r\n            case 'ne':\r\n                var a = grid.right + c.tooltipOffset;\r\n                var b = grid.top + c.tooltipOffset;\r\n                elem.css({right:a, top:b});\r\n                break;\r\n            case 'e':\r\n                var a = grid.right + c.tooltipOffset;\r\n                var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;\r\n                elem.css({right:a, top:b});\r\n                break;\r\n            case 'se':\r\n                var a = grid.right + c.tooltipOffset;\r\n                var b = grid.bottom + c.tooltipOffset;\r\n                elem.css({right:a, bottom:b});\r\n                break;\r\n            case 's':\r\n                var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2;\r\n                var b = grid.bottom + c.tooltipOffset;\r\n                elem.css({left:a, bottom:b});\r\n                break;\r\n            case 'sw':\r\n                var a = grid.left + c.tooltipOffset;\r\n                var b = grid.bottom + c.tooltipOffset;\r\n                elem.css({left:a, bottom:b});\r\n                break;\r\n            case 'w':\r\n                var a = grid.left + c.tooltipOffset;\r\n                var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2;\r\n                elem.css({left:a, top:b});\r\n                break;\r\n            default:  // same as 'se'\r\n                var a = grid.right - c.tooltipOffset;\r\n                var b = grid.bottom + c.tooltipOffset;\r\n                elem.css({right:a, bottom:b});\r\n                break;\r\n        }\r\n        elem = null;\r\n    }\r\n    \r\n    function handleClick (ev, gridpos, datapos, neighbor, plot) {\r\n        ev.preventDefault();\r\n        ev.stopImmediatePropagation();\r\n        var c = plot.plugins.cursor;\r\n        if (c.clickReset) {\r\n            c.resetZoom(plot, c);\r\n        }\r\n        var sel = window.getSelection;\r\n        if (document.selection && document.selection.empty)\r\n        {\r\n            document.selection.empty();\r\n        }\r\n        else if (sel && !sel().isCollapsed) {\r\n            sel().collapse();\r\n        }\r\n        return false;\r\n    }\r\n    \r\n    function handleDblClick (ev, gridpos, datapos, neighbor, plot) {\r\n        ev.preventDefault();\r\n        ev.stopImmediatePropagation();\r\n        var c = plot.plugins.cursor;\r\n        if (c.dblClickReset) {\r\n            c.resetZoom(plot, c);\r\n        }\r\n        var sel = window.getSelection;\r\n        if (document.selection && document.selection.empty)\r\n        {\r\n            document.selection.empty();\r\n        }\r\n        else if (sel && !sel().isCollapsed) {\r\n            sel().collapse();\r\n        }\r\n        return false;\r\n    }\r\n    \r\n    function handleMouseLeave(ev, gridpos, datapos, neighbor, plot) {\r\n        var c = plot.plugins.cursor;\r\n        c.onGrid = false;\r\n        if (c.show) {\r\n            $(ev.target).css('cursor', c.previousCursor);\r\n            if (c.showTooltip && !(c._zoom.zooming && c.showTooltipOutsideZoom && !c.constrainOutsideZoom)) {\r\n                c._tooltipElem.empty();\r\n                c._tooltipElem.hide();\r\n            }\r\n            if (c.zoom) {\r\n                c._zoom.gridpos = gridpos;\r\n                c._zoom.datapos = datapos;\r\n            }\r\n            if (c.showVerticalLine || c.showHorizontalLine) {\r\n                var ctx = c.cursorCanvas._ctx;\r\n                ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n                ctx = null;\r\n            }\r\n            if (c.showCursorLegend) {\r\n                var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label');\r\n                for (var i=0; i<cells.length; i++) {\r\n                    var idx = $(cells[i]).data('seriesIndex');\r\n                    var series = plot.series[idx];\r\n                    var label = series.label.toString();\r\n                    if (plot.legend.escapeHtml) {\r\n                        $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));\r\n                    }\r\n                    else {\r\n                        $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined));\r\n                    }\r\n                \r\n                }        \r\n            }\r\n        }\r\n    }\r\n    \r\n    function handleMouseEnter(ev, gridpos, datapos, neighbor, plot) {\r\n        var c = plot.plugins.cursor;\r\n        c.onGrid = true;\r\n        if (c.show) {\r\n            c.previousCursor = ev.target.style.cursor;\r\n            ev.target.style.cursor = c.style;\r\n            if (c.showTooltip) {\r\n                updateTooltip(gridpos, datapos, plot);\r\n                if (c.followMouse) {\r\n                    moveTooltip(gridpos, plot);\r\n                }\r\n                else {\r\n                    positionTooltip(plot);\r\n                }\r\n                c._tooltipElem.show();\r\n            }\r\n            if (c.showVerticalLine || c.showHorizontalLine) {\r\n                moveLine(gridpos, plot);\r\n            }\r\n        }\r\n\r\n    }    \r\n    \r\n    function handleMouseMove(ev, gridpos, datapos, neighbor, plot) {\r\n        var c = plot.plugins.cursor;\r\n        if (c.show) {\r\n            if (c.showTooltip) {\r\n                updateTooltip(gridpos, datapos, plot);\r\n                if (c.followMouse) {\r\n                    moveTooltip(gridpos, plot);\r\n                }\r\n            }\r\n            if (c.showVerticalLine || c.showHorizontalLine) {\r\n                moveLine(gridpos, plot);\r\n            }\r\n        }\r\n    }\r\n            \r\n    function getEventPosition(ev) {\r\n        var plot = ev.data.plot;\r\n        var go = plot.eventCanvas._elem.offset();\r\n        var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top};\r\n        //////\r\n        // TO DO: handle yMidAxis\r\n        //////\r\n        var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null, yMidAxis:null};\r\n        var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis'];\r\n        var ax = plot.axes;\r\n        var n, axis;\r\n        for (n=11; n>0; n--) {\r\n            axis = an[n-1];\r\n            if (ax[axis].show) {\r\n                dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]);\r\n            }\r\n        }\r\n\r\n        return {offsets:go, gridPos:gridPos, dataPos:dataPos};\r\n    }    \r\n    \r\n    function handleZoomMove(ev) {\r\n        var plot = ev.data.plot;\r\n        var c = plot.plugins.cursor;\r\n        // don't do anything if not on grid.\r\n        if (c.show && c.zoom && c._zoom.started && !c.zoomTarget) {\r\n            ev.preventDefault();\r\n            var ctx = c.zoomCanvas._ctx;\r\n            var positions = getEventPosition(ev);\r\n            var gridpos = positions.gridPos;\r\n            var datapos = positions.dataPos;\r\n            c._zoom.gridpos = gridpos;\r\n            c._zoom.datapos = datapos;\r\n            c._zoom.zooming = true;\r\n            var xpos = gridpos.x;\r\n            var ypos = gridpos.y;\r\n            var height = ctx.canvas.height;\r\n            var width = ctx.canvas.width;\r\n            if (c.showTooltip && !c.onGrid && c.showTooltipOutsideZoom) {\r\n                updateTooltip(gridpos, datapos, plot);\r\n                if (c.followMouse) {\r\n                    moveTooltip(gridpos, plot);\r\n                }\r\n            }\r\n            if (c.constrainZoomTo == 'x') {\r\n                c._zoom.end = [xpos, height];\r\n            }\r\n            else if (c.constrainZoomTo == 'y') {\r\n                c._zoom.end = [width, ypos];\r\n            }\r\n            else {\r\n                c._zoom.end = [xpos, ypos];\r\n            }\r\n            var sel = window.getSelection;\r\n            if (document.selection && document.selection.empty)\r\n            {\r\n                document.selection.empty();\r\n            }\r\n            else if (sel && !sel().isCollapsed) {\r\n                sel().collapse();\r\n            }\r\n            drawZoomBox.call(c);\r\n            ctx = null;\r\n        }\r\n    }\r\n    \r\n    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {\r\n        var c = plot.plugins.cursor;\r\n        if(plot.plugins.mobile){\r\n            $(document).one('vmouseup.jqplot_cursor', {plot:plot}, handleMouseUp);\r\n        } else {\r\n            $(document).one('mouseup.jqplot_cursor', {plot:plot}, handleMouseUp);\r\n        }\r\n        var axes = plot.axes;\r\n        if (document.onselectstart != undefined) {\r\n            c._oldHandlers.onselectstart = document.onselectstart;\r\n            document.onselectstart = function () { return false; };\r\n        }\r\n        if (document.ondrag != undefined) {\r\n            c._oldHandlers.ondrag = document.ondrag;\r\n            document.ondrag = function () { return false; };\r\n        }\r\n        if (document.onmousedown != undefined) {\r\n            c._oldHandlers.onmousedown = document.onmousedown;\r\n            document.onmousedown = function () { return false; };\r\n        }\r\n        if (c.zoom) {\r\n            if (!c.zoomProxy) {\r\n                var ctx = c.zoomCanvas._ctx;\r\n                ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n                ctx = null;\r\n            }\r\n            if (c.constrainZoomTo == 'x') {\r\n                c._zoom.start = [gridpos.x, 0];\r\n            }\r\n            else if (c.constrainZoomTo == 'y') {\r\n                c._zoom.start = [0, gridpos.y];\r\n            }\r\n            else {\r\n                c._zoom.start = [gridpos.x, gridpos.y];\r\n            }\r\n            c._zoom.started = true;\r\n            for (var ax in datapos) {\r\n                // get zoom starting position.\r\n                c._zoom.axes.start[ax] = datapos[ax];\r\n            }  \r\n           if(plot.plugins.mobile){\r\n                $(document).bind('vmousemove.jqplotCursor', {plot:plot}, handleZoomMove);              \r\n            } else {\r\n                $(document).bind('mousemove.jqplotCursor', {plot:plot}, handleZoomMove);              \r\n            }\r\n\r\n        }\r\n    }\r\n    \r\n    function handleMouseUp(ev) {\r\n        var plot = ev.data.plot;\r\n        var c = plot.plugins.cursor;\r\n        if (c.zoom && c._zoom.zooming && !c.zoomTarget) {\r\n            var xpos = c._zoom.gridpos.x;\r\n            var ypos = c._zoom.gridpos.y;\r\n            var datapos = c._zoom.datapos;\r\n            var height = c.zoomCanvas._ctx.canvas.height;\r\n            var width = c.zoomCanvas._ctx.canvas.width;\r\n            var axes = plot.axes;\r\n            \r\n            if (c.constrainOutsideZoom && !c.onGrid) {\r\n                if (xpos < 0) { xpos = 0; }\r\n                else if (xpos > width) { xpos = width; }\r\n                if (ypos < 0) { ypos = 0; }\r\n                else if (ypos > height) { ypos = height; }\r\n                \r\n                for (var axis in datapos) {\r\n                    if (datapos[axis]) {\r\n                        if (axis.charAt(0) == 'x') {\r\n                            datapos[axis] = axes[axis].series_p2u(xpos);\r\n                        }\r\n                        else {\r\n                            datapos[axis] = axes[axis].series_p2u(ypos);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (c.constrainZoomTo == 'x') {\r\n                ypos = height;\r\n            }\r\n            else if (c.constrainZoomTo == 'y') {\r\n                xpos = width;\r\n            }\r\n            c._zoom.end = [xpos, ypos];\r\n            c._zoom.gridpos = {x:xpos, y:ypos};\r\n            \r\n            c.doZoom(c._zoom.gridpos, datapos, plot, c);\r\n        }\r\n        c._zoom.started = false;\r\n        c._zoom.zooming = false;\r\n        \r\n        $(document).unbind('mousemove.jqplotCursor', handleZoomMove);\r\n        \r\n        if (document.onselectstart != undefined && c._oldHandlers.onselectstart != null){\r\n            document.onselectstart = c._oldHandlers.onselectstart;\r\n            c._oldHandlers.onselectstart = null;\r\n        }\r\n        if (document.ondrag != undefined && c._oldHandlers.ondrag != null){\r\n            document.ondrag = c._oldHandlers.ondrag;\r\n            c._oldHandlers.ondrag = null;\r\n        }\r\n        if (document.onmousedown != undefined && c._oldHandlers.onmousedown != null){\r\n            document.onmousedown = c._oldHandlers.onmousedown;\r\n            c._oldHandlers.onmousedown = null;\r\n        }\r\n\r\n    }\r\n    \r\n    function drawZoomBox() {\r\n        var start = this._zoom.start;\r\n        var end = this._zoom.end;\r\n        var ctx = this.zoomCanvas._ctx;\r\n        var l, t, h, w;\r\n        if (end[0] > start[0]) {\r\n            l = start[0];\r\n            w = end[0] - start[0];\r\n        }\r\n        else {\r\n            l = end[0];\r\n            w = start[0] - end[0];\r\n        }\r\n        if (end[1] > start[1]) {\r\n            t = start[1];\r\n            h = end[1] - start[1];\r\n        }\r\n        else {\r\n            t = end[1];\r\n            h = start[1] - end[1];\r\n        }\r\n        ctx.fillStyle = 'rgba(0,0,0,0.2)';\r\n        ctx.strokeStyle = '#999999';\r\n        ctx.lineWidth = 1.0;\r\n        ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n        ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);\r\n        ctx.clearRect(l, t, w, h);\r\n        // IE won't show transparent fill rect, so stroke a rect also.\r\n        ctx.strokeRect(l,t,w,h);\r\n        ctx = null;\r\n    }\r\n    \r\n    $.jqplot.CursorLegendRenderer = function(options) {\r\n        $.jqplot.TableLegendRenderer.call(this, options);\r\n        this.formatString = '%s';\r\n    };\r\n    \r\n    $.jqplot.CursorLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();\r\n    $.jqplot.CursorLegendRenderer.prototype.constructor = $.jqplot.CursorLegendRenderer;\r\n    \r\n    // called in context of a Legend\r\n    $.jqplot.CursorLegendRenderer.prototype.draw = function() {\r\n        if (this._elem) {\r\n            this._elem.emptyForce();\r\n            this._elem = null;\r\n        }\r\n        if (this.show) {\r\n            var series = this._series, s;\r\n            // make a table.  one line label per row.\r\n            var elem = document.createElement('table');\r\n            this._elem = $(elem);\r\n            elem = null;\r\n            this._elem.addClass('jqplot-legend jqplot-cursor-legend');\r\n            this._elem.css('position', 'absolute');\r\n        \r\n            var pad = false;\r\n            for (var i = 0; i< series.length; i++) {\r\n                s = series[i];\r\n                if (s.show && s.showLabel) {\r\n                    var lt = $.jqplot.sprintf(this.formatString, s.label.toString());\r\n                    if (lt) {\r\n                        var color = s.color;\r\n                        if (s._stack && !s.fill) {\r\n                            color = '';\r\n                        }\r\n                        addrow.call(this, lt, color, pad, i);\r\n                        pad = true;\r\n                    }\r\n                    // let plugins add more rows to legend.  Used by trend line plugin.\r\n                    for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) {\r\n                        var item = $.jqplot.addLegendRowHooks[j].call(this, s);\r\n                        if (item) {\r\n                            addrow.call(this, item.label, item.color, pad);\r\n                            pad = true;\r\n                        } \r\n                    }\r\n                }\r\n            }\r\n            series = s = null;\r\n            delete series;\r\n            delete s;\r\n        }\r\n        \r\n        function addrow(label, color, pad, idx) {\r\n            var rs = (pad) ? this.rowSpacing : '0';\r\n            var tr = $('<tr class=\"jqplot-legend jqplot-cursor-legend\"></tr>').appendTo(this._elem);\r\n            tr.data('seriesIndex', idx);\r\n            $('<td class=\"jqplot-legend jqplot-cursor-legend-swatch\" style=\"padding-top:'+rs+';\">'+\r\n                '<div style=\"border:1px solid #cccccc;padding:0.2em;\">'+\r\n                '<div class=\"jqplot-cursor-legend-swatch\" style=\"background-color:'+color+';\"></div>'+\r\n                '</div></td>').appendTo(tr);\r\n            var td = $('<td class=\"jqplot-legend jqplot-cursor-legend-label\" style=\"vertical-align:middle;padding-top:'+rs+';\"></td>');\r\n            td.appendTo(tr);\r\n            td.data('seriesIndex', idx);\r\n            if (this.escapeHtml) {\r\n                td.text(label);\r\n            }\r\n            else {\r\n                td.html(label);\r\n            }\r\n            tr = null;\r\n            td = null;\r\n        }\r\n        return this._elem;\r\n    };\r\n    \r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.dateAxisRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {  \r\n    /**\r\n     * Class: $.jqplot.DateAxisRenderer\r\n     * A plugin for a jqPlot to render an axis as a series of date values.\r\n     * This renderer has no options beyond those supplied by the <Axis> class.\r\n     * It supplies its own tick formatter, so the tickOptions.formatter option\r\n     * should not be overridden.\r\n     * \r\n     * Thanks to Ken Synder for his enhanced Date instance methods which are\r\n     * included with this code <http://kendsnyder.com/sandbox/date/>.\r\n     * \r\n     * To use this renderer, include the plugin in your source\r\n     * > <script type=\"text/javascript\" language=\"javascript\" src=\"plugins/jqplot.dateAxisRenderer.js\"></script>\r\n     * \r\n     * and supply the appropriate options to your plot\r\n     * \r\n     * > {axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer}}}\r\n     * \r\n     * Dates can be passed into the axis in almost any recognizable value and \r\n     * will be parsed.  They will be rendered on the axis in the format\r\n     * specified by tickOptions.formatString.  e.g. tickOptions.formatString = '%Y-%m-%d'.\r\n     * \r\n     * Accecptable format codes \r\n     * are:\r\n     * \r\n     * > Code    Result                  Description\r\n     * >             == Years ==\r\n     * > %Y      2008                Four-digit year\r\n     * > %y      08                  Two-digit year\r\n     * >             == Months ==\r\n     * > %m      09                  Two-digit month\r\n     * > %#m     9                   One or two-digit month\r\n     * > %B      September           Full month name\r\n     * > %b      Sep                 Abbreviated month name\r\n     * >             == Days ==\r\n     * > %d      05                  Two-digit day of month\r\n     * > %#d     5                   One or two-digit day of month\r\n     * > %e      5                   One or two-digit day of month\r\n     * > %A      Sunday              Full name of the day of the week\r\n     * > %a      Sun                 Abbreviated name of the day of the week\r\n     * > %w      0                   Number of the day of the week (0 = Sunday, 6 = Saturday)\r\n     * > %o      th                  The ordinal suffix string following the day of the month\r\n     * >             == Hours ==\r\n     * > %H      23                  Hours in 24-hour format (two digits)\r\n     * > %#H     3                   Hours in 24-hour integer format (one or two digits)\r\n     * > %I      11                  Hours in 12-hour format (two digits)\r\n     * > %#I     3                   Hours in 12-hour integer format (one or two digits)\r\n     * > %p      PM                  AM or PM\r\n     * >             == Minutes ==\r\n     * > %M      09                  Minutes (two digits)\r\n     * > %#M     9                   Minutes (one or two digits)\r\n     * >             == Seconds ==\r\n     * > %S      02                  Seconds (two digits)\r\n     * > %#S     2                   Seconds (one or two digits)\r\n     * > %s      1206567625723       Unix timestamp (Seconds past 1970-01-01 00:00:00)\r\n     * >             == Milliseconds ==\r\n     * > %N      008                 Milliseconds (three digits)\r\n     * > %#N     8                   Milliseconds (one to three digits)\r\n     * >             == Timezone ==\r\n     * > %O      360                 difference in minutes between local time and GMT\r\n     * > %Z      Mountain Standard Time  Name of timezone as reported by browser\r\n     * > %G      -06:00              Hours and minutes between GMT\r\n     * >             == Shortcuts ==\r\n     * > %F      2008-03-26          %Y-%m-%d\r\n     * > %T      05:06:30            %H:%M:%S\r\n     * > %X      05:06:30            %H:%M:%S\r\n     * > %x      03/26/08            %m/%d/%y\r\n     * > %D      03/26/08            %m/%d/%y\r\n     * > %#c     Wed Mar 26 15:31:00 2008  %a %b %e %H:%M:%S %Y\r\n     * > %v      3-Sep-2008          %e-%b-%Y\r\n     * > %R      15:31               %H:%M\r\n     * > %r      3:31:00 PM          %I:%M:%S %p\r\n     * >             == Characters ==\r\n     * > %n      \\n                  Newline\r\n     * > %t      \\t                  Tab\r\n     * > %%      %                   Percent Symbol \r\n     */\r\n    $.jqplot.DateAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n        this.date = new $.jsDate();\r\n    };\r\n\r\n    var second = 1000;\r\n    var minute = 60 * second;\r\n    var hour = 60 * minute;\r\n    var day = 24 * hour;\r\n    var week = 7 * day;\r\n\r\n    // these are less definitive\r\n    var month = 30.4368499 * day;\r\n    var year = 365.242199 * day;\r\n\r\n    var daysInMonths = [31,28,31,30,31,30,31,30,31,30,31,30];\r\n    // array of consistent nice intervals.  Longer intervals\r\n    // will depend on days in month, days in year, etc.\r\n    var niceFormatStrings = ['%M:%S.%#N', '%M:%S.%#N', '%M:%S.%#N', '%M:%S', '%M:%S', '%M:%S', '%M:%S', '%H:%M:%S', '%H:%M:%S', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%a %H:%M', '%a %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%v', '%v', '%v', '%v', '%v', '%v', '%v'];\r\n    var niceIntervals = [0.1*second, 0.2*second, 0.5*second, second, 2*second, 5*second, 10*second, 15*second, 30*second, minute, 2*minute, 5*minute, 10*minute, 15*minute, 30*minute, hour, 2*hour, 4*hour, 6*hour, 8*hour, 12*hour, day, 2*day, 3*day, 4*day, 5*day, week, 2*week];\r\n\r\n    var niceMonthlyIntervals = [];\r\n\r\n    function bestDateInterval(min, max, titarget) {\r\n        // iterate through niceIntervals to find one closest to titarget\r\n        var badness = Number.MAX_VALUE;\r\n        var temp, bestTi, bestfmt;\r\n        for (var i=0, l=niceIntervals.length; i < l; i++) {\r\n            temp = Math.abs(titarget - niceIntervals[i]);\r\n            if (temp < badness) {\r\n                badness = temp;\r\n                bestTi = niceIntervals[i];\r\n                bestfmt = niceFormatStrings[i];\r\n            }\r\n        }\r\n\r\n        return [bestTi, bestfmt];\r\n    }\r\n    \r\n    $.jqplot.DateAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.DateAxisRenderer.prototype.constructor = $.jqplot.DateAxisRenderer;\r\n    \r\n    $.jqplot.DateTickFormatter = function(format, val) {\r\n        if (!format) {\r\n            format = '%Y/%m/%d';\r\n        }\r\n        return $.jsDate.strftime(val, format);\r\n    };\r\n    \r\n    $.jqplot.DateAxisRenderer.prototype.init = function(options){\r\n        // prop: tickRenderer\r\n        // A class of a rendering engine for creating the ticks labels displayed on the plot, \r\n        // See <$.jqplot.AxisTickRenderer>.\r\n        // this.tickRenderer = $.jqplot.AxisTickRenderer;\r\n        // this.labelRenderer = $.jqplot.AxisLabelRenderer;\r\n        this.tickOptions.formatter = $.jqplot.DateTickFormatter;\r\n        // prop: tickInset\r\n        // Controls the amount to inset the first and last ticks from \r\n        // the edges of the grid, in multiples of the tick interval.\r\n        // 0 is no inset, 0.5 is one half a tick interval, 1 is a full\r\n        // tick interval, etc.\r\n        this.tickInset = 0;\r\n        // prop: drawBaseline\r\n        // True to draw the axis baseline.\r\n        this.drawBaseline = true;\r\n        // prop: baselineWidth\r\n        // width of the baseline in pixels.\r\n        this.baselineWidth = null;\r\n        // prop: baselineColor\r\n        // CSS color spec for the baseline.\r\n        this.baselineColor = null;\r\n        this.daTickInterval = null;\r\n        this._daTickInterval = null;\r\n        \r\n        $.extend(true, this, options);\r\n        \r\n        var db = this._dataBounds,\r\n            stats, \r\n            sum,\r\n            s,\r\n            d,\r\n            pd,\r\n            sd,\r\n            intv;\r\n        \r\n        // Go through all the series attached to this axis and find\r\n        // the min/max bounds for this axis.\r\n        for (var i=0; i<this._series.length; i++) {\r\n            stats = {intervals:[], frequencies:{}, sortedIntervals:[], min:null, max:null, mean:null};\r\n            sum = 0;\r\n            s = this._series[i];\r\n            d = s.data;\r\n            pd = s._plotData;\r\n            sd = s._stackData;\r\n            intv = 0;\r\n            \r\n            for (var j=0; j<d.length; j++) { \r\n                if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                    d[j][0] = new $.jsDate(d[j][0]).getTime();\r\n                    pd[j][0] = new $.jsDate(d[j][0]).getTime();\r\n                    sd[j][0] = new $.jsDate(d[j][0]).getTime();\r\n                    if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) {\r\n                        db.min = d[j][0];\r\n                    }\r\n                    if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) {\r\n                        db.max = d[j][0];\r\n                    }\r\n                    if (j>0) {\r\n                        intv = Math.abs(d[j][0] - d[j-1][0]);\r\n                        stats.intervals.push(intv);\r\n                        if (stats.frequencies.hasOwnProperty(intv)) {\r\n                            stats.frequencies[intv] += 1;\r\n                        }\r\n                        else {\r\n                            stats.frequencies[intv] = 1;\r\n                        }\r\n                    }\r\n                    sum += intv;\r\n                    \r\n                }              \r\n                else {\r\n                    d[j][1] = new $.jsDate(d[j][1]).getTime();\r\n                    pd[j][1] = new $.jsDate(d[j][1]).getTime();\r\n                    sd[j][1] = new $.jsDate(d[j][1]).getTime();\r\n                    if ((d[j][1] != null && d[j][1] < db.min) || db.min == null) {\r\n                        db.min = d[j][1];\r\n                    }\r\n                    if ((d[j][1] != null && d[j][1] > db.max) || db.max == null) {\r\n                        db.max = d[j][1];\r\n                    }\r\n                    if (j>0) {\r\n                        intv = Math.abs(d[j][1] - d[j-1][1]);\r\n                        stats.intervals.push(intv);\r\n                        if (stats.frequencies.hasOwnProperty(intv)) {\r\n                            stats.frequencies[intv] += 1;\r\n                        }\r\n                        else {\r\n                            stats.frequencies[intv] = 1;\r\n                        }\r\n                    }\r\n                }\r\n                sum += intv;              \r\n            }\r\n\r\n            if (s.renderer.bands) {\r\n                if (s.renderer.bands.hiData.length) {\r\n                    var bd = s.renderer.bands.hiData;\r\n                    for (var j=0, l=bd.length; j < l; j++) {\r\n                        if (this.name === 'xaxis' || this.name === 'x2axis') {\r\n                            bd[j][0] = new $.jsDate(bd[j][0]).getTime();\r\n                            if ((bd[j][0] != null && bd[j][0] > db.max) || db.max == null) {\r\n                                db.max = bd[j][0];\r\n                            }                        \r\n                        }              \r\n                        else {\r\n                            bd[j][1] = new $.jsDate(bd[j][1]).getTime();\r\n                            if ((bd[j][1] != null && bd[j][1] > db.max) || db.max == null) {\r\n                                db.max = bd[j][1];\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                if (s.renderer.bands.lowData.length) {\r\n                    var bd = s.renderer.bands.lowData;\r\n                    for (var j=0, l=bd.length; j < l; j++) {\r\n                        if (this.name === 'xaxis' || this.name === 'x2axis') {\r\n                            bd[j][0] = new $.jsDate(bd[j][0]).getTime();\r\n                            if ((bd[j][0] != null && bd[j][0] < db.min) || db.min == null) {\r\n                                db.min = bd[j][0];\r\n                            }                       \r\n                        }              \r\n                        else {\r\n                            bd[j][1] = new $.jsDate(bd[j][1]).getTime();\r\n                            if ((bd[j][1] != null && bd[j][1] < db.min) || db.min == null) {\r\n                                db.min = bd[j][1];\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n            \r\n            var tempf = 0,\r\n                tempn=0;\r\n            for (var n in stats.frequencies) {\r\n                stats.sortedIntervals.push({interval:n, frequency:stats.frequencies[n]});\r\n            }\r\n            stats.sortedIntervals.sort(function(a, b){\r\n                return b.frequency - a.frequency;\r\n            });\r\n            \r\n            stats.min = $.jqplot.arrayMin(stats.intervals);\r\n            stats.max = $.jqplot.arrayMax(stats.intervals);\r\n            stats.mean = sum/d.length;\r\n            this._intervalStats.push(stats);\r\n            stats = sum = s = d = pd = sd = null;\r\n        }\r\n        db = null;\r\n        \r\n    };\r\n    \r\n    // called with scope of an axis\r\n    $.jqplot.DateAxisRenderer.prototype.reset = function() {\r\n        this.min = this._options.min;\r\n        this.max = this._options.max;\r\n        this.tickInterval = this._options.tickInterval;\r\n        this.numberTicks = this._options.numberTicks;\r\n        this._autoFormatString = '';\r\n        if (this._overrideFormatString && this.tickOptions && this.tickOptions.formatString) {\r\n            this.tickOptions.formatString = '';\r\n        }\r\n        this.daTickInterval = this._daTickInterval;\r\n        // this._ticks = this.__ticks;\r\n    };\r\n    \r\n    $.jqplot.DateAxisRenderer.prototype.createTicks = function(plot) {\r\n        // we're are operating on an axis here\r\n        var ticks = this._ticks;\r\n        var userTicks = this.ticks;\r\n        var name = this.name;\r\n        // databounds were set on axis initialization.\r\n        var db = this._dataBounds;\r\n        var iv = this._intervalStats;\r\n        var dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height;\r\n        var interval;\r\n        var min, max;\r\n        var pos1, pos2;\r\n        var tt, i;\r\n        var threshold = 30;\r\n        var insetMult = 1;\r\n        var daTickInterval = null;\r\n        \r\n        // if user specified a tick interval, convert to usable.\r\n        if (this.tickInterval != null)\r\n        {\r\n            // if interval is a number or can be converted to one, use it.\r\n            // Assume it is in SECONDS!!!\r\n            if (Number(this.tickInterval)) {\r\n                daTickInterval = [Number(this.tickInterval), 'seconds'];\r\n            }\r\n            // else, parse out something we can build from.\r\n            else if (typeof this.tickInterval == \"string\") {\r\n                var parts = this.tickInterval.split(' ');\r\n                if (parts.length == 1) {\r\n                    daTickInterval = [1, parts[0]];\r\n                }\r\n                else if (parts.length == 2) {\r\n                    daTickInterval = [parts[0], parts[1]];\r\n                }\r\n            }\r\n        }\r\n\r\n        var tickInterval = this.tickInterval;\r\n        \r\n        // if we already have ticks, use them.\r\n        // ticks must be in order of increasing value.\r\n        \r\n        min = new $.jsDate((this.min != null) ? this.min : db.min).getTime();\r\n        max = new $.jsDate((this.max != null) ? this.max : db.max).getTime();\r\n\r\n        // see if we're zooming.  if we are, don't use the min and max we're given,\r\n        // but compute some nice ones.  They will be reset later.\r\n\r\n        var cursor = plot.plugins.cursor;\r\n\r\n        if (cursor && cursor._zoom && cursor._zoom.zooming) {\r\n            this.min = null;\r\n            this.max = null;\r\n        }\r\n\r\n        var range = max - min;\r\n\r\n        if (this.tickOptions == null || !this.tickOptions.formatString) {\r\n            this._overrideFormatString = true;\r\n        }\r\n        \r\n        if (userTicks.length) {\r\n            // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed\r\n            for (i=0; i<userTicks.length; i++){\r\n                var ut = userTicks[i];\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                if (ut.constructor == Array) {\r\n                    t.value = new $.jsDate(ut[0]).getTime();\r\n                    t.label = ut[1];\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(t.value, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n                \r\n                else {\r\n                    t.value = new $.jsDate(ut).getTime();\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(t.value, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n            this.numberTicks = userTicks.length;\r\n            this.min = this._ticks[0].value;\r\n            this.max = this._ticks[this.numberTicks-1].value;\r\n            this.daTickInterval = [(this.max - this.min) / (this.numberTicks - 1)/1000, 'seconds'];\r\n        }\r\n\r\n        ////////\r\n        // We don't have any ticks yet, let's make some!\r\n        ////////\r\n\r\n        // special case when there is only one point, make three tick marks to center the point\r\n        else if (this.min == null && this.max == null && db.min == db.max)\r\n        {\r\n             var onePointOpts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null});\r\n             var delta = 300000;\r\n             this.min = db.min - delta;\r\n             this.max = db.max + delta;\r\n             this.numberTicks = 3;\r\n\r\n             for(var i=this.min;i<=this.max;i+= delta)\r\n             {\r\n                 onePointOpts.value = i;\r\n\r\n                 var t = new this.tickRenderer(onePointOpts);\r\n\r\n                 if (this._overrideFormatString && this._autoFormatString != '') {\r\n                    t.formatString = this._autoFormatString;\r\n                 }\r\n\r\n                 t.showLabel = false;\r\n                 t.showMark = false;\r\n\r\n                 this._ticks.push(t);\r\n             }\r\n\r\n             if(this.showTicks) {\r\n                 this._ticks[1].showLabel = true;\r\n             }\r\n             if(this.showTickMarks) {\r\n                 this._ticks[1].showTickMarks = true;\r\n             }                   \r\n        }\r\n        // if user specified min and max are null, we set those to make best ticks.\r\n        else if (this.min == null && this.max == null) {\r\n\r\n            var opts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null});\r\n\r\n            // want to find a nice interval \r\n            var nttarget,\r\n                titarget;\r\n\r\n            // if no tickInterval or numberTicks options specified,  make a good guess.\r\n            if (!this.tickInterval && !this.numberTicks) {\r\n                var tdim = Math.max(dim, threshold+1);\r\n                // how many ticks to put on the axis?\r\n                // date labels tend to be long.  If ticks not rotated,\r\n                // don't use too many and have a high spacing factor.\r\n                // If we are rotating ticks, use a lower factor.\r\n                var spacingFactor = 115;\r\n                if (this.tickRenderer === $.jqplot.CanvasAxisTickRenderer && this.tickOptions.angle) {\r\n                    spacingFactor = 115 - 40 * Math.abs(Math.sin(this.tickOptions.angle/180*Math.PI));\r\n                }\r\n\r\n                nttarget =  Math.ceil((tdim-threshold)/spacingFactor + 1);\r\n                titarget = (max - min) / (nttarget - 1);\r\n            }\r\n\r\n            // If tickInterval is specified, we'll try to honor it.\r\n            // Not guaranteed to get this interval, but we'll get as close as\r\n            // we can.\r\n            // tickInterval will be used before numberTicks, that is if\r\n            // both are specified, numberTicks will be ignored.\r\n            else if (this.tickInterval) {\r\n                titarget = new $.jsDate(0).add(daTickInterval[0], daTickInterval[1]).getTime();\r\n            }\r\n\r\n            // if numberTicks specified, try to honor it.\r\n            // Not guaranteed, but will try to get close.\r\n            else if (this.numberTicks) {\r\n                nttarget = this.numberTicks;\r\n                titarget = (max - min) / (nttarget - 1);\r\n            }\r\n\r\n            // If we can use an interval of 2 weeks or less, pick best one\r\n            if (titarget <= 19*day) {\r\n                var ret = bestDateInterval(min, max, titarget);\r\n                var tempti = ret[0];\r\n                this._autoFormatString = ret[1];\r\n\r\n                min = new $.jsDate(min);\r\n                min = Math.floor((min.getTime() - min.getUtcOffset())/tempti) * tempti + min.getUtcOffset();\r\n\r\n                nttarget = Math.ceil((max - min) / tempti) + 1;\r\n                this.min = min;\r\n                this.max = min + (nttarget - 1) * tempti;\r\n\r\n                // if max is less than max, add an interval\r\n                if (this.max < max) {\r\n                    this.max += tempti;\r\n                    nttarget += 1;\r\n                }\r\n                this.tickInterval = tempti;\r\n                this.numberTicks = nttarget;\r\n\r\n                for (var i=0; i<nttarget; i++) {\r\n                    opts.value = this.min + i * tempti;\r\n                    t = new this.tickRenderer(opts);\r\n                    \r\n                    if (this._overrideFormatString && this._autoFormatString != '') {\r\n                        t.formatString = this._autoFormatString;\r\n                    }\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    this._ticks.push(t);\r\n                }\r\n\r\n                insetMult = this.tickInterval;\r\n            }\r\n\r\n            // should we use a monthly interval?\r\n            else if (titarget <= 9 * month) {\r\n\r\n                this._autoFormatString = '%v';\r\n\r\n                // how many months in an interval?\r\n                var intv = Math.round(titarget/month);\r\n                if (intv < 1) {\r\n                    intv = 1;\r\n                }\r\n                else if (intv > 6) {\r\n                    intv = 6;\r\n                }\r\n\r\n                // figure out the starting month and ending month.\r\n                var mstart = new $.jsDate(min).setDate(1).setHours(0,0,0,0);\r\n\r\n                // See if max ends exactly on a month\r\n                var tempmend = new $.jsDate(max);\r\n                var mend = new $.jsDate(max).setDate(1).setHours(0,0,0,0);\r\n\r\n                if (tempmend.getTime() !== mend.getTime()) {\r\n                    mend = mend.add(1, 'month');\r\n                }\r\n\r\n                var nmonths = mend.diff(mstart, 'month');\r\n\r\n                nttarget = Math.ceil(nmonths/intv) + 1;\r\n\r\n                this.min = mstart.getTime();\r\n                this.max = mstart.clone().add((nttarget - 1) * intv, 'month').getTime();\r\n                this.numberTicks = nttarget;\r\n\r\n                for (var i=0; i<nttarget; i++) {\r\n                    if (i === 0) {\r\n                        opts.value = mstart.getTime();\r\n                    }\r\n                    else {\r\n                        opts.value = mstart.add(intv, 'month').getTime();\r\n                    }\r\n                    t = new this.tickRenderer(opts);\r\n                    \r\n                    if (this._overrideFormatString && this._autoFormatString != '') {\r\n                        t.formatString = this._autoFormatString;\r\n                    }\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    this._ticks.push(t);\r\n                }\r\n\r\n                insetMult = intv * month;\r\n            }\r\n\r\n            // use yearly intervals\r\n            else {\r\n\r\n                this._autoFormatString = '%v';\r\n\r\n                // how many years in an interval?\r\n                var intv = Math.round(titarget/year);\r\n                if (intv < 1) {\r\n                    intv = 1;\r\n                }\r\n\r\n                // figure out the starting and ending years.\r\n                var mstart = new $.jsDate(min).setMonth(0, 1).setHours(0,0,0,0);\r\n                var mend = new $.jsDate(max).add(1, 'year').setMonth(0, 1).setHours(0,0,0,0);\r\n\r\n                var nyears = mend.diff(mstart, 'year');\r\n\r\n                nttarget = Math.ceil(nyears/intv) + 1;\r\n\r\n                this.min = mstart.getTime();\r\n                this.max = mstart.clone().add((nttarget - 1) * intv, 'year').getTime();\r\n                this.numberTicks = nttarget;\r\n\r\n                for (var i=0; i<nttarget; i++) {\r\n                    if (i === 0) {\r\n                        opts.value = mstart.getTime();\r\n                    }\r\n                    else {\r\n                        opts.value = mstart.add(intv, 'year').getTime();\r\n                    }\r\n                    t = new this.tickRenderer(opts);\r\n                    \r\n                    if (this._overrideFormatString && this._autoFormatString != '') {\r\n                        t.formatString = this._autoFormatString;\r\n                    }\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    this._ticks.push(t);\r\n                }\r\n\r\n                insetMult = intv * year;\r\n            }\r\n        }\r\n\r\n        ////////\r\n        // Some option(s) specified, work around that.\r\n        ////////\r\n        \r\n        else {      \r\n            if (name == 'xaxis' || name == 'x2axis') {\r\n                dim = this._plotDimensions.width;\r\n            }\r\n            else {\r\n                dim = this._plotDimensions.height;\r\n            }\r\n            \r\n            // if min, max and number of ticks specified, user can't specify interval.\r\n            if (this.min != null && this.max != null && this.numberTicks != null) {\r\n                this.tickInterval = null;\r\n            }\r\n            \r\n            if (this.tickInterval != null && daTickInterval != null) {\r\n                this.daTickInterval = daTickInterval;\r\n            }\r\n            \r\n            // if min and max are same, space them out a bit\r\n            if (min == max) {\r\n                var adj = 24*60*60*500;  // 1/2 day\r\n                min -= adj;\r\n                max += adj;\r\n            }\r\n\r\n            range = max - min;\r\n            \r\n            var optNumTicks = 2 + parseInt(Math.max(0, dim-100)/100, 10);\r\n            \r\n            \r\n            var rmin, rmax;\r\n            \r\n            rmin = (this.min != null) ? new $.jsDate(this.min).getTime() : min - range/2*(this.padMin - 1);\r\n            rmax = (this.max != null) ? new $.jsDate(this.max).getTime() : max + range/2*(this.padMax - 1);\r\n            this.min = rmin;\r\n            this.max = rmax;\r\n            range = this.max - this.min;\r\n            \r\n            if (this.numberTicks == null){\r\n                // if tickInterval is specified by user, we will ignore computed maximum.\r\n                // max will be equal or greater to fit even # of ticks.\r\n                if (this.daTickInterval != null) {\r\n                    var nc = new $.jsDate(this.max).diff(this.min, this.daTickInterval[1], true);\r\n                    this.numberTicks = Math.ceil(nc/this.daTickInterval[0]) +1;\r\n                    // this.max = new $.jsDate(this.min).add(this.numberTicks-1, this.daTickInterval[1]).getTime();\r\n                    this.max = new $.jsDate(this.min).add((this.numberTicks-1) * this.daTickInterval[0], this.daTickInterval[1]).getTime();\r\n                }\r\n                else if (dim > 200) {\r\n                    this.numberTicks = parseInt(3+(dim-200)/100, 10);\r\n                }\r\n                else {\r\n                    this.numberTicks = 2;\r\n                }\r\n            }\r\n            \r\n            insetMult = range / (this.numberTicks-1)/1000;\r\n\r\n            if (this.daTickInterval == null) {\r\n                this.daTickInterval = [insetMult, 'seconds'];\r\n            }\r\n\r\n\r\n            for (var i=0; i<this.numberTicks; i++){\r\n                var min = new $.jsDate(this.min);\r\n                tt = min.add(i*this.daTickInterval[0], this.daTickInterval[1]).getTime();\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                // var t = new $.jqplot.AxisTickRenderer(this.tickOptions);\r\n                if (!this.showTicks) {\r\n                    t.showLabel = false;\r\n                    t.showMark = false;\r\n                }\r\n                else if (!this.showTickMarks) {\r\n                    t.showMark = false;\r\n                }\r\n                t.setTick(tt, this.name);\r\n                this._ticks.push(t);\r\n            }\r\n        }\r\n\r\n        if (this.tickInset) {\r\n            this.min = this.min - this.tickInset * insetMult;\r\n            this.max = this.max + this.tickInset * insetMult;\r\n        }\r\n\r\n        if (this._daTickInterval == null) {\r\n            this._daTickInterval = this.daTickInterval;    \r\n        }\r\n\r\n        ticks = null;\r\n    };\r\n   \r\n})(jQuery);\r\n\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.donutRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.DonutRenderer\r\n     * Plugin renderer to draw a donut chart.\r\n     * x values, if present, will be used as slice labels.\r\n     * y values give slice size.\r\n     * \r\n     * To use this renderer, you need to include the \r\n     * donut renderer plugin, for example:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.donutRenderer.js\"></script>\r\n     * \r\n     * Properties described here are passed into the $.jqplot function\r\n     * as options on the series renderer.  For example:\r\n     * \r\n     * > plot2 = $.jqplot('chart2', [s1, s2], {\r\n     * >     seriesDefaults: {\r\n     * >         renderer:$.jqplot.DonutRenderer,\r\n     * >         rendererOptions:{\r\n     * >              sliceMargin: 2,\r\n     * >              innerDiameter: 110,\r\n     * >              startAngle: -90\r\n     * >          }\r\n     * >      }\r\n     * > });\r\n     * \r\n     * A donut plot will trigger events on the plot target\r\n     * according to user interaction.  All events return the event object,\r\n     * the series index, the point (slice) index, and the point data for \r\n     * the appropriate slice.\r\n     * \r\n     * 'jqplotDataMouseOver' - triggered when user mouseing over a slice.\r\n     * 'jqplotDataHighlight' - triggered the first time user mouses over a slice,\r\n     * if highlighting is enabled.\r\n     * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of\r\n     * a highlighted slice.\r\n     * 'jqplotDataClick' - triggered when the user clicks on a slice.\r\n     * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if\r\n     * the \"captureRightClick\" option is set to true on the plot.\r\n     */\r\n    $.jqplot.DonutRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.DonutRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.DonutRenderer.prototype.constructor = $.jqplot.DonutRenderer;\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.DonutRenderer.prototype.init = function(options, plot) {\r\n        // Group: Properties\r\n        //\r\n        // prop: diameter\r\n        // Outer diameter of the donut, auto computed by default\r\n        this.diameter = null;\r\n        // prop: innerDiameter\r\n        // Inner diameter of the donut, auto calculated by default.\r\n        // If specified will override thickness value.\r\n        this.innerDiameter = null;\r\n        // prop: thickness\r\n        // thickness of the donut, auto computed by default\r\n        // Overridden by if innerDiameter is specified.\r\n        this.thickness = null;\r\n        // prop: padding\r\n        // padding between the donut and plot edges, legend, etc.\r\n        this.padding = 20;\r\n        // prop: sliceMargin\r\n        // angular spacing between donut slices in degrees.\r\n        this.sliceMargin = 0;\r\n        // prop: ringMargin\r\n        // pixel distance between rings, or multiple series in a donut plot.\r\n        // null will compute ringMargin based on sliceMargin.\r\n        this.ringMargin = null;\r\n        // prop: fill\r\n        // true or false, whether to fil the slices.\r\n        this.fill = true;\r\n        // prop: shadowOffset\r\n        // offset of the shadow from the slice and offset of \r\n        // each succesive stroke of the shadow from the last.\r\n        this.shadowOffset = 2;\r\n        // prop: shadowAlpha\r\n        // transparency of the shadow (0 = transparent, 1 = opaque)\r\n        this.shadowAlpha = 0.07;\r\n        // prop: shadowDepth\r\n        // number of strokes to apply to the shadow, \r\n        // each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 5;\r\n        // prop: highlightMouseOver\r\n        // True to highlight slice when moused over.\r\n        // This must be false to enable highlightMouseDown to highlight when clicking on a slice.\r\n        this.highlightMouseOver = true;\r\n        // prop: highlightMouseDown\r\n        // True to highlight when a mouse button is pressed over a slice.\r\n        // This will be disabled if highlightMouseOver is true.\r\n        this.highlightMouseDown = false;\r\n        // prop: highlightColors\r\n        // an array of colors to use when highlighting a slice.\r\n        this.highlightColors = [];\r\n        // prop: dataLabels\r\n        // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices.\r\n        // Defaults to percentage of each pie slice.\r\n        this.dataLabels = 'percent';\r\n        // prop: showDataLabels\r\n        // true to show data labels on slices.\r\n        this.showDataLabels = false;\r\n        // prop: totalLabel\r\n        // true to show total label in the centre\r\n        this.totalLabel = false;\r\n        // prop: dataLabelFormatString\r\n        // Format string for data labels.  If none, '%s' is used for \"label\" and for arrays, '%d' for value and '%d%%' for percentage.\r\n        this.dataLabelFormatString = null;\r\n        // prop: dataLabelThreshold\r\n        // Threshhold in percentage (0 - 100) of pie area, below which no label will be displayed.\r\n        // This applies to all label types, not just to percentage labels.\r\n        this.dataLabelThreshold = 3;\r\n        // prop: dataLabelPositionFactor\r\n        // A Multiplier (0-1) of the pie radius which controls position of label on slice.\r\n        // Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie.\r\n        this.dataLabelPositionFactor = 0.4;\r\n        // prop: dataLabelNudge\r\n        // Number of pixels to slide the label away from (+) or toward (-) the center of the pie.\r\n        this.dataLabelNudge = 0;\r\n        // prop: startAngle\r\n        // Angle to start drawing donut in degrees.  \r\n        // According to orientation of canvas coordinate system:\r\n        // 0 = on the positive x axis\r\n        // -90 = on the positive y axis.\r\n        // 90 = on the negaive y axis.\r\n        // 180 or - 180 = on the negative x axis.\r\n        this.startAngle = 0;\r\n        this.tickRenderer = $.jqplot.DonutTickRenderer;\r\n        // Used as check for conditions where donut shouldn't be drawn.\r\n        this._drawData = true;\r\n        this._type = 'donut';\r\n        \r\n        // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver\r\n        if (options.highlightMouseDown && options.highlightMouseOver == null) {\r\n            options.highlightMouseOver = false;\r\n        }\r\n        \r\n        $.extend(true, this, options);\r\n        if (this.diameter != null) {\r\n            this.diameter = this.diameter - this.sliceMargin;\r\n        }\r\n        this._diameter = null;\r\n        this._innerDiameter = null;\r\n        this._radius = null;\r\n        this._innerRadius = null;\r\n        this._thickness = null;\r\n        // references to the previous series in the plot to properly calculate diameters\r\n        // and thicknesses of nested rings.\r\n        this._previousSeries = [];\r\n        this._numberSeries = 1;\r\n        // array of [start,end] angles arrays, one for each slice.  In radians.\r\n        this._sliceAngles = [];\r\n        // index of the currenty highlighted point, if any\r\n        this._highlightedPoint = null;\r\n        \r\n        // set highlight colors if none provided\r\n        if (this.highlightColors.length == 0) {\r\n            for (var i=0; i<this.seriesColors.length; i++){\r\n                var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);\r\n                var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n                var sum = newrgb[0] + newrgb[1] + newrgb[2];\r\n                for (var j=0; j<3; j++) {\r\n                    // when darkening, lowest color component can be is 60.\r\n                    newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);\r\n                    newrgb[j] = parseInt(newrgb[j], 10);\r\n                }\r\n                this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');\r\n            }\r\n        }\r\n        \r\n        plot.postParseOptionsHooks.addOnce(postParseOptions);\r\n        plot.postInitHooks.addOnce(postInit);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);\r\n        plot.eventListenerHooks.addOnce('jqplotClick', handleClick);\r\n        plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);\r\n        plot.postDrawHooks.addOnce(postPlotDraw);\r\n        \r\n        \r\n    };\r\n    \r\n    $.jqplot.DonutRenderer.prototype.setGridData = function(plot) {\r\n        // set gridData property.  This will hold angle in radians of each data point.\r\n        var stack = [];\r\n        var td = [];\r\n        var sa = this.startAngle/180*Math.PI;\r\n        var tot = 0;\r\n        // don't know if we have any valid data yet, so set plot to not draw.\r\n        this._drawData = false;\r\n        for (var i=0; i<this.data.length; i++){\r\n            if (this.data[i][1] != 0) {\r\n                // we have data, O.K. to draw.\r\n                this._drawData = true;\r\n            }\r\n            stack.push(this.data[i][1]);\r\n            td.push([this.data[i][0]]);\r\n            if (i>0) {\r\n                stack[i] += stack[i-1];\r\n            }\r\n            tot += this.data[i][1];\r\n        }\r\n        var fact = Math.PI*2/stack[stack.length - 1];\r\n        \r\n        for (var i=0; i<stack.length; i++) {\r\n            td[i][1] = stack[i] * fact;\r\n            td[i][2] = this.data[i][1]/tot;\r\n        }\r\n        this.gridData = td;\r\n    };\r\n    \r\n    $.jqplot.DonutRenderer.prototype.makeGridData = function(data, plot) {\r\n        var stack = [];\r\n        var td = [];\r\n        var tot = 0;\r\n        var sa = this.startAngle/180*Math.PI;\r\n        // don't know if we have any valid data yet, so set plot to not draw.\r\n        this._drawData = false;\r\n        for (var i=0; i<data.length; i++){\r\n            if (this.data[i][1] != 0) {\r\n                // we have data, O.K. to draw.\r\n                this._drawData = true;\r\n            }\r\n            stack.push(data[i][1]);\r\n            td.push([data[i][0]]);\r\n            if (i>0) {\r\n                stack[i] += stack[i-1];\r\n            }\r\n            tot += data[i][1];\r\n        }\r\n        var fact = Math.PI*2/stack[stack.length - 1];\r\n        \r\n        for (var i=0; i<stack.length; i++) {\r\n            td[i][1] = stack[i] * fact;\r\n            td[i][2] = data[i][1]/tot;\r\n        }\r\n        this._totalAmount = tot;        \r\n        return td;\r\n    };\r\n    \r\n    $.jqplot.DonutRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) {\r\n        var r = this._diameter / 2;\r\n        var ri = r - this._thickness;\r\n        var fill = this.fill;\r\n        // var lineWidth = this.lineWidth;\r\n        ctx.save();\r\n        ctx.translate(this._center[0], this._center[1]);\r\n        // ctx.translate(this.sliceMargin*Math.cos((ang1+ang2)/2), this.sliceMargin*Math.sin((ang1+ang2)/2));\r\n        \r\n        if (isShadow) {\r\n            for (var i=0; i<this.shadowDepth; i++) {\r\n                ctx.save();\r\n                ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));\r\n                doDraw();\r\n            }\r\n        }\r\n        \r\n        else {\r\n            doDraw();\r\n        }\r\n        \r\n        function doDraw () {\r\n            // Fix for IE and Chrome that can't seem to draw circles correctly.\r\n            // ang2 should always be <= 2 pi since that is the way the data is converted.\r\n             if (ang2 > 6.282 + this.startAngle) {\r\n                ang2 = 6.282 + this.startAngle;\r\n                if (ang1 > ang2) {\r\n                    ang1 = 6.281 + this.startAngle;\r\n                }\r\n            }\r\n            // Fix for IE, where it can't seem to handle 0 degree angles.  Also avoids\r\n            // ugly line on unfilled donuts.\r\n            if (ang1 >= ang2) {\r\n                return;\r\n            }\r\n            ctx.beginPath();  \r\n            ctx.fillStyle = color;\r\n            ctx.strokeStyle = color;\r\n            // ctx.lineWidth = lineWidth;\r\n            ctx.arc(0, 0, r, ang1, ang2, false);\r\n            ctx.lineTo(ri*Math.cos(ang2), ri*Math.sin(ang2));\r\n            ctx.arc(0,0, ri, ang2, ang1, true);\r\n            ctx.closePath();\r\n            if (fill) {\r\n                ctx.fill();\r\n            }\r\n            else {\r\n                ctx.stroke();\r\n            }\r\n        }\r\n        \r\n        if (isShadow) {\r\n            for (var i=0; i<this.shadowDepth; i++) {\r\n                ctx.restore();\r\n            }\r\n        }\r\n        \r\n        ctx.restore();\r\n    };\r\n    \r\n    // called with scope of series\r\n    $.jqplot.DonutRenderer.prototype.draw = function (ctx, gd, options, plot) {\r\n        var i;\r\n        var opts = (options != undefined) ? options : {};\r\n        // offset and direction of offset due to legend placement\r\n        var offx = 0;\r\n        var offy = 0;\r\n        var trans = 1;\r\n        // var colorGenerator = new this.colorGenerator(this.seriesColors);\r\n        if (options.legendInfo && options.legendInfo.placement == 'insideGrid') {\r\n            var li = options.legendInfo;\r\n            switch (li.location) {\r\n                case 'nw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'w':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'sw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'ne':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'e':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'se':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'n':\r\n                    offy = li.height + li.yoffset;\r\n                    break;\r\n                case 's':\r\n                    offy = li.height + li.yoffset;\r\n                    trans = -1;\r\n                    break;\r\n                default:\r\n                    break;\r\n            }\r\n        }\r\n        \r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        //see http://stackoverflow.com/questions/20221461/hidpi-retina-plot-drawing\r\n        var cw = parseInt(ctx.canvas.style.width);\r\n        var ch = parseInt(ctx.canvas.style.height);\r\n        var w = cw - offx - 2 * this.padding;\r\n        var h = ch - offy - 2 * this.padding;\r\n        var mindim = Math.min(w,h);\r\n        var d = mindim;\r\n        var ringmargin =  (this.ringMargin == null) ? this.sliceMargin * 2.0 : this.ringMargin;\r\n        \r\n        for (var i=0; i<this._previousSeries.length; i++) {\r\n            d -= 2.0 * this._previousSeries[i]._thickness + 2.0 * ringmargin;\r\n        }\r\n        this._diameter = this.diameter || d;\r\n        if (this.innerDiameter != null) {\r\n            var od = (this._numberSeries > 1 && this.index > 0) ? this._previousSeries[0]._diameter : this._diameter;\r\n            this._thickness = this.thickness || (od - this.innerDiameter - 2.0*ringmargin*this._numberSeries) / this._numberSeries/2.0;\r\n        }\r\n        else {\r\n            this._thickness = this.thickness || mindim / 2 / (this._numberSeries + 1) * 0.85;\r\n        }\r\n        if (this._diameter < 6) {\r\n            $.jqplot.log(\"Diameter of donut too small, not rendering.\");\r\n            return;\r\n        }\r\n        var r = this._radius = this._diameter/2;\r\n        this._innerRadius = this._radius - this._thickness;\r\n        var sa = this.startAngle / 180 * Math.PI;\r\n        this._center = [(cw - trans * offx)/2 + trans * offx, (ch - trans*offy)/2 + trans * offy];\r\n        \r\n        if (this.shadow) {\r\n            var shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';\r\n            for (var i=0; i<gd.length; i++) {\r\n                var ang1 = (i == 0) ? sa : gd[i-1][1] + sa;\r\n                // Adjust ang1 and ang2 for sliceMargin\r\n                ang1 += this.sliceMargin/180*Math.PI;\r\n                this.renderer.drawSlice.call (this, ctx, ang1, gd[i][1]+sa, shadowColor, true);\r\n            }\r\n            \r\n        }\r\n        for (var i=0; i<gd.length; i++) {\r\n            var ang1 = (i == 0) ? sa : gd[i-1][1] + sa;\r\n            // Adjust ang1 and ang2 for sliceMargin\r\n            ang1 += this.sliceMargin/180*Math.PI;\r\n            var ang2 = gd[i][1] + sa;\r\n            this._sliceAngles.push([ang1, ang2]);\r\n            this.renderer.drawSlice.call (this, ctx, ang1, ang2, this.seriesColors[i], false);\r\n            \r\n            if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) {\r\n                var fstr, avgang = (ang1+ang2)/2, label;\r\n                \r\n                if (this.dataLabels == 'label') {\r\n                    fstr = this.dataLabelFormatString || '%s';\r\n                    label = $.jqplot.sprintf(fstr, gd[i][0]);\r\n                }\r\n                else if (this.dataLabels == 'value') {\r\n                    fstr = this.dataLabelFormatString || '%d';\r\n                    label = $.jqplot.sprintf(fstr, this.data[i][1]);\r\n                }\r\n                else if (this.dataLabels == 'percent') {\r\n                    fstr = this.dataLabelFormatString || '%d%%';\r\n                    label = $.jqplot.sprintf(fstr, gd[i][2]*100);\r\n                }\r\n                else if (this.dataLabels.constructor == Array) {\r\n                    fstr = this.dataLabelFormatString || '%s';\r\n                    label = $.jqplot.sprintf(fstr, this.dataLabels[i]);\r\n                }\r\n                \r\n                var fact = this._innerRadius + this._thickness * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;\r\n                \r\n                var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left;\r\n                var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top;\r\n                \r\n                var labelelem = $('<span class=\"jqplot-donut-series jqplot-data-label\" style=\"position:absolute;\">' + label + '</span>').insertBefore(plot.eventCanvas._elem);\r\n                x -= labelelem.width()/2;\r\n                y -= labelelem.height()/2;\r\n                x = Math.round(x);\r\n                y = Math.round(y);\r\n                labelelem.css({left: x, top: y});\r\n            }\r\n        }\r\n        if (this.totalLabel) {\r\n            var totalLabel = $('<div class=\"jqplot-data-label\" style=\"position:absolute\">' + this._totalAmount + '</div>').insertAfter(plot.eventCanvas._elem);\r\n            totalLabel.css({left: this._center[0], top: this._center[1]});\r\n        }\r\n    };\r\n    \r\n    $.jqplot.DonutAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.DonutAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.DonutAxisRenderer.prototype.constructor = $.jqplot.DonutAxisRenderer;\r\n        \r\n    \r\n    // There are no traditional axes on a donut chart.  We just need to provide\r\n    // dummy objects with properties so the plot will render.\r\n    // called with scope of axis object.\r\n    $.jqplot.DonutAxisRenderer.prototype.init = function(options){\r\n        //\r\n        this.tickRenderer = $.jqplot.DonutTickRenderer;\r\n        $.extend(true, this, options);\r\n        // I don't think I'm going to need _dataBounds here.\r\n        // have to go Axis scaling in a way to fit chart onto plot area\r\n        // and provide u2p and p2u functionality for mouse cursor, etc.\r\n        // for convienence set _dataBounds to 0 and 100 and\r\n        // set min/max to 0 and 100.\r\n        this._dataBounds = {min:0, max:100};\r\n        this.min = 0;\r\n        this.max = 100;\r\n        this.showTicks = false;\r\n        this.ticks = [];\r\n        this.showMark = false;\r\n        this.show = false; \r\n    };\r\n    \r\n    \r\n    \r\n    \r\n    $.jqplot.DonutLegendRenderer = function(){\r\n        $.jqplot.TableLegendRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.DonutLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();\r\n    $.jqplot.DonutLegendRenderer.prototype.constructor = $.jqplot.DonutLegendRenderer;\r\n    \r\n    /**\r\n     * Class: $.jqplot.DonutLegendRenderer\r\n     * Legend Renderer specific to donut plots.  Set by default\r\n     * when user creates a donut plot.\r\n     */\r\n    $.jqplot.DonutLegendRenderer.prototype.init = function(options) {\r\n        // Group: Properties\r\n        //\r\n        // prop: numberRows\r\n        // Maximum number of rows in the legend.  0 or null for unlimited.\r\n        this.numberRows = null;\r\n        // prop: numberColumns\r\n        // Maximum number of columns in the legend.  0 or null for unlimited.\r\n        this.numberColumns = null;\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    // called with context of legend\r\n    $.jqplot.DonutLegendRenderer.prototype.draw = function() {\r\n        var legend = this;\r\n        if (this.show) {\r\n            var series = this._series;\r\n            var ss = 'position:absolute;';\r\n            ss += (this.background) ? 'background:'+this.background+';' : '';\r\n            ss += (this.border) ? 'border:'+this.border+';' : '';\r\n            ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';\r\n            ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : '';\r\n            ss += (this.textColor) ? 'color:'+this.textColor+';' : '';\r\n            ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : '';\r\n            ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : '';\r\n            ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : '';\r\n            ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : '';\r\n            this._elem = $('<table class=\"jqplot-table-legend\" style=\"'+ss+'\"></table>');\r\n            // Donut charts legends don't go by number of series, but by number of data points\r\n            // in the series.  Refactor things here for that.\r\n            \r\n            var pad = false, \r\n                reverse = false,\r\n                nr, nc;\r\n            var s = series[0];\r\n            var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);\r\n            \r\n            if (s.show) {\r\n                var pd = s.data;\r\n                if (this.numberRows) {\r\n                    nr = this.numberRows;\r\n                    if (!this.numberColumns){\r\n                        nc = Math.ceil(pd.length/nr);\r\n                    }\r\n                    else{\r\n                        nc = this.numberColumns;\r\n                    }\r\n                }\r\n                else if (this.numberColumns) {\r\n                    nc = this.numberColumns;\r\n                    nr = Math.ceil(pd.length/this.numberColumns);\r\n                }\r\n                else {\r\n                    nr = pd.length;\r\n                    nc = 1;\r\n                }\r\n                \r\n                var i, j, tr, td1, td2, lt, rs, color;\r\n                var idx = 0;    \r\n                \r\n                for (i=0; i<nr; i++) {\r\n                    if (reverse){\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').prependTo(this._elem);\r\n                    }\r\n                    else{\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').appendTo(this._elem);\r\n                    }\r\n                    for (j=0; j<nc; j++) {\r\n                        if (idx < pd.length){\r\n                            lt = this.labels[idx] || pd[idx][0].toString();\r\n                            color = colorGenerator.next();\r\n                            if (!reverse){\r\n                                if (i>0){\r\n                                    pad = true;\r\n                                }\r\n                                else{\r\n                                    pad = false;\r\n                                }\r\n                            }\r\n                            else{\r\n                                if (i == nr -1){\r\n                                    pad = false;\r\n                                }\r\n                                else{\r\n                                    pad = true;\r\n                                }\r\n                            }\r\n                            rs = (pad) ? this.rowSpacing : '0';\r\n                \r\n                            td1 = $('<td class=\"jqplot-table-legend\" style=\"text-align:center;padding-top:'+rs+';\">'+\r\n                                '<div><div class=\"jqplot-table-legend-swatch\" style=\"border-color:'+color+';\"></div>'+\r\n                                '</div></td>');\r\n                            td2 = $('<td class=\"jqplot-table-legend\" style=\"padding-top:'+rs+';\"></td>');\r\n                            if (this.escapeHtml){\r\n                                td2.text(lt);\r\n                            }\r\n                            else {\r\n                                td2.html(lt);\r\n                            }\r\n                            if (reverse) {\r\n                                td2.prependTo(tr);\r\n                                td1.prependTo(tr);\r\n                            }\r\n                            else {\r\n                                td1.appendTo(tr);\r\n                                td2.appendTo(tr);\r\n                            }\r\n                            pad = true;\r\n                        }\r\n                        idx++;\r\n                    }   \r\n                }\r\n            }\r\n        }\r\n        return this._elem;                \r\n    };\r\n    \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        options = options || {};\r\n        options.axesDefaults = options.axesDefaults || {};\r\n        options.legend = options.legend || {};\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        // only set these if there is a donut series\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer == $.jqplot.DonutRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer == $.jqplot.DonutRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.DonutAxisRenderer;\r\n            options.legend.renderer = $.jqplot.DonutLegendRenderer;\r\n            options.legend.preDraw = true;\r\n            options.seriesDefaults.pointLabels = {show: false};\r\n        }\r\n    }\r\n    \r\n    // called with scope of plot.\r\n    function postInit(target, data, options) {\r\n        // if multiple series, add a reference to the previous one so that\r\n        // donut rings can nest.\r\n        for (var i=1; i<this.series.length; i++) {\r\n            if (!this.series[i]._previousSeries.length){\r\n                for (var j=0; j<i; j++) {\r\n                    if (this.series[i].renderer.constructor == $.jqplot.DonutRenderer && this.series[j].renderer.constructor == $.jqplot.DonutRenderer) {\r\n                        this.series[i]._previousSeries.push(this.series[j]);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        for (i=0; i<this.series.length; i++) {\r\n            if (this.series[i].renderer.constructor == $.jqplot.DonutRenderer) {\r\n                this.series[i]._numberSeries = this.series.length;\r\n                // don't allow mouseover and mousedown at same time.\r\n                if (this.series[i].highlightMouseOver) {\r\n                    this.series[i].highlightMouseDown = false;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    \r\n    var postParseOptionsRun = false;\r\n    // called with scope of plot\r\n    function postParseOptions(options) {\r\n        for (var i=0; i<this.series.length; i++) {\r\n            this.series[i].seriesColors = this.seriesColors;\r\n            this.series[i].colorGenerator = $.jqplot.colorGenerator;\r\n        }\r\n    }\r\n    \r\n    function highlight (plot, sidx, pidx) {\r\n        var s = plot.series[sidx];\r\n        var canvas = plot.plugins.donutRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        s._highlightedPoint = pidx;\r\n        plot.plugins.donutRenderer.highlightedSeriesIndex = sidx;\r\n        s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColors[pidx], false);\r\n    }\r\n    \r\n    function unhighlight (plot) {\r\n        var canvas = plot.plugins.donutRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            plot.series[i]._highlightedPoint = null;\r\n        }\r\n        plot.plugins.donutRenderer.highlightedSeriesIndex = null;\r\n        plot.target.trigger('jqplotDataUnhighlight');\r\n    }\r\n \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt1 = jQuery.Event('jqplotDataMouseOver');\r\n            evt1.pageX = ev.pageX;\r\n            evt1.pageY = ev.pageY;\r\n            plot.target.trigger(evt1, ins);\r\n            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    } \r\n    \r\n    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.donutRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {\r\n        var idx = plot.plugins.donutRenderer.highlightedSeriesIndex;\r\n        if (idx != null && plot.series[idx].highlightMouseDown) {\r\n            unhighlight(plot);\r\n        }\r\n    }\r\n    \r\n    function handleClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt = jQuery.Event('jqplotDataClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var idx = plot.plugins.donutRenderer.highlightedSeriesIndex;\r\n            if (idx != null && plot.series[idx].highlightMouseDown) {\r\n                unhighlight(plot);\r\n            }\r\n            var evt = jQuery.Event('jqplotDataRightClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }    \r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    function postPlotDraw() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.donutRenderer && this.plugins.donutRenderer.highlightCanvas) {\r\n            this.plugins.donutRenderer.highlightCanvas.resetCanvas();\r\n            this.plugins.donutRenderer.highlightCanvas = null;\r\n        }\r\n\r\n        this.plugins.donutRenderer = {highlightedSeriesIndex:null};\r\n        this.plugins.donutRenderer.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        // do we have any data labels?  if so, put highlight canvas before those\r\n        // Fix for broken jquery :first selector with canvas (VML) elements.\r\n        var labels = $(this.targetId+' .jqplot-data-label');\r\n        if (labels.length) {\r\n            $(labels[0]).before(this.plugins.donutRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-donutRenderer-highlight-canvas', this._plotDimensions, this));\r\n        }\r\n        // else put highlight canvas before event canvas.\r\n        else {\r\n            this.eventCanvas._elem.before(this.plugins.donutRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-donutRenderer-highlight-canvas', this._plotDimensions, this));\r\n        }\r\n        var hctx = this.plugins.donutRenderer.highlightCanvas.setContext();\r\n        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });\r\n    }\r\n    \r\n    $.jqplot.preInitHooks.push(preInit);\r\n    \r\n    $.jqplot.DonutTickRenderer = function() {\r\n        $.jqplot.AxisTickRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.DonutTickRenderer.prototype = new $.jqplot.AxisTickRenderer();\r\n    $.jqplot.DonutTickRenderer.prototype.constructor = $.jqplot.DonutTickRenderer;\r\n    \r\n})(jQuery);\r\n    \r\n    \r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.dragable.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    \r\n    /**\r\n     * Class: $.jqplot.Dragable\r\n     * Plugin to make plotted points dragable by the user.\r\n     */\r\n    $.jqplot.Dragable = function(options) {\r\n        // Group: Properties\r\n        this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false});\r\n        this.shapeRenderer = new $.jqplot.ShapeRenderer();\r\n        this.isDragging = false;\r\n        this.isOver = false;\r\n        this._ctx;\r\n        this._elem;\r\n        this._point;\r\n        this._gridData;\r\n        // prop: color\r\n        // CSS color spec for the dragged point (and adjacent line segment or bar).\r\n        this.color;\r\n        // prop: constrainTo\r\n        // Constrain dragging motion to an axis or to none.\r\n        // Allowable values are 'none', 'x', 'y'\r\n        this.constrainTo = 'none';  // 'x', 'y', or 'none';\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    function DragCanvas() {\r\n        $.jqplot.GenericCanvas.call(this);\r\n        this.isDragging = false;\r\n        this.isOver = false;\r\n        this._neighbor;\r\n        this._cursors = [];\r\n    }\r\n    \r\n    DragCanvas.prototype = new $.jqplot.GenericCanvas();\r\n    DragCanvas.prototype.constructor = DragCanvas;\r\n    \r\n    \r\n    // called within scope of series\r\n    $.jqplot.Dragable.parseOptions = function (defaults, opts) {\r\n        var options = opts || {};\r\n        this.plugins.dragable = new $.jqplot.Dragable(options.dragable);\r\n        // since this function is called before series options are parsed,\r\n        // we can set this here and it will be overridden if needed.\r\n        this.isDragable = $.jqplot.config.enablePlugins;\r\n    };\r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    // add a new DragCanvas object to the plot plugins to handle drawing on this new canvas.\r\n    $.jqplot.Dragable.postPlotDraw = function() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.dragable && this.plugins.dragable.highlightCanvas) {\r\n            this.plugins.dragable.highlightCanvas.resetCanvas();\r\n            this.plugins.dragable.highlightCanvas = null;\r\n        }\r\n\r\n        this.plugins.dragable = {previousCursor:'auto', isOver:false};\r\n        this.plugins.dragable.dragCanvas = new DragCanvas();\r\n        \r\n        this.eventCanvas._elem.before(this.plugins.dragable.dragCanvas.createElement(this._gridPadding, 'jqplot-dragable-canvas', this._plotDimensions, this));\r\n        var dctx = this.plugins.dragable.dragCanvas.setContext();\r\n    };\r\n    \r\n    //$.jqplot.preInitHooks.push($.jqplot.Dragable.init);\r\n    $.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Dragable.parseOptions);\r\n    $.jqplot.postDrawHooks.push($.jqplot.Dragable.postPlotDraw);\r\n    $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);\r\n    $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleDown]);\r\n    $.jqplot.eventListenerHooks.push(['jqplotMouseUp', handleUp]);\r\n\r\n    \r\n    function initDragPoint(plot, neighbor) {\r\n        var s = plot.series[neighbor.seriesIndex];\r\n        var drag = s.plugins.dragable;\r\n        \r\n        // first, init the mark renderer for the dragged point\r\n        var smr = s.markerRenderer;\r\n        var mr = drag.markerRenderer;\r\n        mr.style = smr.style;\r\n        mr.lineWidth = smr.lineWidth + 2.5;\r\n        mr.size = smr.size + 5;\r\n        if (!drag.color) {\r\n            var rgba = $.jqplot.getColorComponents(smr.color);\r\n            var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n            var alpha = (rgba[3] >= 0.6) ? rgba[3]*0.6 : rgba[3]*(2-rgba[3]);\r\n            drag.color = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+alpha+')';\r\n        }\r\n        mr.color = drag.color;\r\n        mr.init();\r\n\r\n        var start = (neighbor.pointIndex > 0) ? neighbor.pointIndex - 1 : 0;\r\n        var end = neighbor.pointIndex+2;\r\n        drag._gridData = s.gridData.slice(start, end);\r\n    }\r\n    \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (plot.plugins.dragable.dragCanvas.isDragging) {\r\n            var dc = plot.plugins.dragable.dragCanvas;\r\n            var dp = dc._neighbor;\r\n            var s = plot.series[dp.seriesIndex];\r\n            var drag = s.plugins.dragable;\r\n            var gd = s.gridData;\r\n            \r\n            // compute the new grid position with any constraints.\r\n            var x = (drag.constrainTo == 'y') ? dp.gridData[0] : gridpos.x;\r\n            var y = (drag.constrainTo == 'x') ? dp.gridData[1] : gridpos.y;\r\n            \r\n            // compute data values for any listeners.\r\n            var xu = s._xaxis.series_p2u(x);\r\n            var yu = s._yaxis.series_p2u(y);\r\n            \r\n            // clear the canvas then redraw effect at new position.\r\n            var ctx = dc._ctx;\r\n            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n            \r\n            // adjust our gridData for the new mouse position\r\n            if (dp.pointIndex > 0) {\r\n                drag._gridData[1] = [x, y];\r\n            }\r\n            else {\r\n                drag._gridData[0] = [x, y];\r\n            }\r\n            plot.series[dp.seriesIndex].draw(dc._ctx, {gridData:drag._gridData, shadow:false, preventJqPlotSeriesDrawTrigger:true, color:drag.color, markerOptions:{color:drag.color, shadow:false}, trendline:{show:false}});\r\n            plot.target.trigger('jqplotSeriesPointChange', [dp.seriesIndex, dp.pointIndex, [xu,yu], [x,y]]);\r\n        }\r\n        else if (neighbor != null) {\r\n            var series = plot.series[neighbor.seriesIndex];\r\n            if (series.isDragable) {\r\n                var dc = plot.plugins.dragable.dragCanvas;\r\n                if (!dc.isOver) {\r\n                    dc._cursors.push(ev.target.style.cursor);\r\n                    ev.target.style.cursor = \"pointer\";\r\n                }\r\n                dc.isOver = true;\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            var dc = plot.plugins.dragable.dragCanvas;\r\n            if (dc.isOver) {\r\n                ev.target.style.cursor = dc._cursors.pop();\r\n                dc.isOver = false;\r\n            }\r\n        }\r\n    }\r\n    \r\n    function handleDown(ev, gridpos, datapos, neighbor, plot) {\r\n        var dc = plot.plugins.dragable.dragCanvas;\r\n        dc._cursors.push(ev.target.style.cursor);\r\n        if (neighbor != null) {\r\n            var s = plot.series[neighbor.seriesIndex];\r\n            var drag = s.plugins.dragable;\r\n            if (s.isDragable && !dc.isDragging) {\r\n                dc._neighbor = neighbor;\r\n                dc.isDragging = true;\r\n                initDragPoint(plot, neighbor);\r\n                drag.markerRenderer.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], dc._ctx);\r\n                ev.target.style.cursor = \"move\";\r\n                plot.target.trigger('jqplotDragStart', [neighbor.seriesIndex, neighbor.pointIndex, gridpos, datapos]);\r\n            }\r\n        }\r\n        // Just in case of a hickup, we'll clear the drag canvas and reset.\r\n        else {\r\n           var ctx = dc._ctx;\r\n           ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n           dc.isDragging = false;\r\n        }\r\n    }\r\n    \r\n    function handleUp(ev, gridpos, datapos, neighbor, plot) {\r\n        if (plot.plugins.dragable.dragCanvas.isDragging) {\r\n            var dc = plot.plugins.dragable.dragCanvas;\r\n            // clear the canvas\r\n            var ctx = dc._ctx;\r\n            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n            dc.isDragging = false;\r\n            // redraw the series canvas at the new point.\r\n            var dp = dc._neighbor;\r\n            var s = plot.series[dp.seriesIndex];\r\n            var drag = s.plugins.dragable;\r\n            // compute the new grid position with any constraints.\r\n            var x = (drag.constrainTo == 'y') ? dp.data[0] : datapos[s.xaxis];\r\n            var y = (drag.constrainTo == 'x') ? dp.data[1] : datapos[s.yaxis];\r\n            // var x = datapos[s.xaxis];\r\n            // var y = datapos[s.yaxis];\r\n            s.data[dp.pointIndex][0] = x;\r\n            s.data[dp.pointIndex][1] = y;\r\n            plot.drawSeries({preventJqPlotSeriesDrawTrigger:true}, dp.seriesIndex);\r\n            dc._neighbor = null;\r\n            ev.target.style.cursor = dc._cursors.pop();\r\n            plot.target.trigger('jqplotDragStop', [gridpos, datapos]);\r\n        }\r\n    }\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.enhancedLegendRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    // class $.jqplot.EnhancedLegendRenderer\r\n    // Legend renderer which can specify the number of rows and/or columns in the legend.\r\n    $.jqplot.EnhancedLegendRenderer = function(){\r\n        $.jqplot.TableLegendRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.EnhancedLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();\r\n    $.jqplot.EnhancedLegendRenderer.prototype.constructor = $.jqplot.EnhancedLegendRenderer;\r\n    \r\n    // called with scope of legend.\r\n    $.jqplot.EnhancedLegendRenderer.prototype.init = function(options) {\r\n        // prop: numberRows\r\n        // Maximum number of rows in the legend.  0 or null for unlimited.\r\n        this.numberRows = null;\r\n        // prop: numberColumns\r\n        // Maximum number of columns in the legend.  0 or null for unlimited.\r\n        this.numberColumns = null;\r\n        // prop: seriesToggle\r\n        // false to not enable series on/off toggling on the legend.\r\n        // true or a fadein/fadeout speed (number of milliseconds or 'fast', 'normal', 'slow') \r\n        // to enable show/hide of series on click of legend item.\r\n        this.seriesToggle = 'normal';\r\n        // prop: seriesToggleReplot\r\n        // True to replot the chart after toggling series on/off.\r\n        // This will set the series show property to false.\r\n        // This allows for rescaling or other maniplation of chart.\r\n        // Set to an options object (e.g. {resetAxes: true}) for replot options.\r\n        this.seriesToggleReplot = false;\r\n        // prop: disableIEFading\r\n        // true to toggle series with a show/hide method only and not allow fading in/out.  \r\n        // This is to overcome poor performance of fade in some versions of IE.\r\n        this.disableIEFading = true;\r\n        $.extend(true, this, options);\r\n        \r\n        if (this.seriesToggle) {\r\n            $.jqplot.postDrawHooks.push(postDraw);\r\n        }\r\n    };\r\n    \r\n    // called with scope of legend\r\n    $.jqplot.EnhancedLegendRenderer.prototype.draw = function(offsets, plot) {\r\n        var legend = this;\r\n        if (this.show) {\r\n            var series = this._series;\r\n            var s;\r\n            var ss = 'position:absolute;';\r\n            ss += (this.background) ? 'background:'+this.background+';' : '';\r\n            ss += (this.border) ? 'border:'+this.border+';' : '';\r\n            ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';\r\n            ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : '';\r\n            ss += (this.textColor) ? 'color:'+this.textColor+';' : '';\r\n            ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : '';\r\n            ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : '';\r\n            ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : '';\r\n            ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : '';\r\n            this._elem = $('<table class=\"jqplot-table-legend\" style=\"'+ss+'\"></table>');\r\n            if (this.seriesToggle) {\r\n                this._elem.css('z-index', '3');\r\n            }\r\n        \r\n            var pad = false, \r\n                reverse = false,\r\n                nr, nc;\r\n            if (this.numberRows) {\r\n                nr = this.numberRows;\r\n                if (!this.numberColumns){\r\n                    nc = Math.ceil(series.length/nr);\r\n                }\r\n                else{\r\n                    nc = this.numberColumns;\r\n                }\r\n            }\r\n            else if (this.numberColumns) {\r\n                nc = this.numberColumns;\r\n                nr = Math.ceil(series.length/this.numberColumns);\r\n            }\r\n            else {\r\n                nr = series.length;\r\n                nc = 1;\r\n            }\r\n                \r\n            var i, j, tr, td1, td2, lt, rs, div, div0, div1;\r\n            var idx = 0;\r\n            // check to see if we need to reverse\r\n            for (i=series.length-1; i>=0; i--) {\r\n                if (nc == 1 && series[i]._stack || series[i].renderer.constructor == $.jqplot.BezierCurveRenderer){\r\n                    reverse = true;\r\n                }\r\n            }    \r\n                \r\n            for (i=0; i<nr; i++) {\r\n                tr = $(document.createElement('tr'));\r\n                tr.addClass('jqplot-table-legend');\r\n                if (reverse){\r\n                    tr.prependTo(this._elem);\r\n                }\r\n                else{\r\n                    tr.appendTo(this._elem);\r\n                }\r\n                for (j=0; j<nc; j++) {\r\n                    if (idx < series.length && (series[idx].show || series[idx].showLabel)){\r\n                        s = series[idx];\r\n                        lt = this.labels[idx] || s.label.toString();\r\n                        if (lt) {\r\n                            var color = s.color;\r\n                            if (!reverse){\r\n                                if (i>0){\r\n                                    pad = true;\r\n                                }\r\n                                else{\r\n                                    pad = false;\r\n                                }\r\n                            }\r\n                            else{\r\n                                if (i == nr -1){\r\n                                    pad = false;\r\n                                }\r\n                                else{\r\n                                    pad = true;\r\n                                }\r\n                            }\r\n                            rs = (pad) ? this.rowSpacing : '0';\r\n\r\n                            td1 = $(document.createElement('td'));\r\n                            td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');\r\n                            td1.css({textAlign: 'center', paddingTop: rs});\r\n\r\n                            div0 = $(document.createElement('div'));\r\n                            div0.addClass('jqplot-table-legend-swatch-outline');\r\n                            div1 = $(document.createElement('div'));\r\n                            div1.addClass('jqplot-table-legend-swatch');\r\n                            div1.css({backgroundColor: color, borderColor: color});\r\n\r\n                            td1.append(div0.append(div1));\r\n\r\n                            td2 = $(document.createElement('td'));\r\n                            td2.addClass('jqplot-table-legend jqplot-table-legend-label');\r\n                            td2.css('paddingTop', rs);\r\n                    \r\n                            // td1 = $('<td class=\"jqplot-table-legend\" style=\"text-align:center;padding-top:'+rs+';\">'+\r\n                            //     '<div><div class=\"jqplot-table-legend-swatch\" style=\"background-color:'+color+';border-color:'+color+';\"></div>'+\r\n                            //     '</div></td>');\r\n                            // td2 = $('<td class=\"jqplot-table-legend\" style=\"padding-top:'+rs+';\"></td>');\r\n                            if (this.escapeHtml){\r\n                                td2.text(lt);\r\n                            }\r\n                            else {\r\n                                td2.html(lt);\r\n                            }\r\n                            if (reverse) {\r\n                                if (this.showLabels) {td2.prependTo(tr);}\r\n                                if (this.showSwatches) {td1.prependTo(tr);}\r\n                            }\r\n                            else {\r\n                                if (this.showSwatches) {td1.appendTo(tr);}\r\n                                if (this.showLabels) {td2.appendTo(tr);}\r\n                            }\r\n                            \r\n                            if (this.seriesToggle) {\r\n\r\n                                // add an overlay for clicking series on/off\r\n                                // div0 = $(document.createElement('div'));\r\n                                // div0.addClass('jqplot-table-legend-overlay');\r\n                                // div0.css({position:'relative', left:0, top:0, height:'100%', width:'100%'});\r\n                                // tr.append(div0);\r\n\r\n                                var speed;\r\n                                if (typeof(this.seriesToggle) === 'string' || typeof(this.seriesToggle) === 'number') {\r\n                                    if (!$.jqplot.use_excanvas || !this.disableIEFading) {\r\n                                        speed = this.seriesToggle;\r\n                                    }\r\n                                } \r\n                                if (this.showSwatches) {\r\n                                    td1.bind('click', {series:s, speed:speed, plot: plot, replot:this.seriesToggleReplot}, handleToggle);\r\n                                    td1.addClass('jqplot-seriesToggle');\r\n                                }\r\n                                if (this.showLabels)  {\r\n                                    td2.bind('click', {series:s, speed:speed, plot: plot, replot:this.seriesToggleReplot}, handleToggle);\r\n                                    td2.addClass('jqplot-seriesToggle');\r\n                                }\r\n\r\n                                // for series that are already hidden, add the hidden class\r\n                                if (!s.show && s.showLabel) {\r\n                                    td1.addClass('jqplot-series-hidden');\r\n                                    td2.addClass('jqplot-series-hidden');\r\n                                }\r\n                            }\r\n                            \r\n                            pad = true;\r\n                        }\r\n                    }\r\n                    idx++;\r\n                }\r\n                \r\n                td1 = td2 = div0 = div1 = null;   \r\n            }\r\n        }\r\n        return this._elem;\r\n    };\r\n\r\n    var handleToggle = function (ev) {\r\n        var d = ev.data,\r\n            s = d.series,\r\n            replot = d.replot,\r\n            plot = d.plot,\r\n            speed = d.speed,\r\n            sidx = s.index,\r\n            showing = false;\r\n\r\n        if (s.canvas._elem.is(':hidden') || !s.show) {\r\n            showing = true;\r\n        }\r\n\r\n        var doLegendToggle = function() {\r\n\r\n            if (replot) {\r\n                var opts = {};\r\n\r\n                if ($.isPlainObject(replot)) {\r\n                    $.extend(true, opts, replot);\r\n                }\r\n\r\n                plot.replot(opts);\r\n                // if showing, there was no canvas element to fade in, so hide here\r\n                // and then do a fade in.\r\n                if (showing && speed) {\r\n                    var s = plot.series[sidx];\r\n\r\n                    if (s.shadowCanvas._elem) {\r\n                        s.shadowCanvas._elem.hide().fadeIn(speed);\r\n                    }\r\n                    s.canvas._elem.hide().fadeIn(speed);\r\n                    s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).hide().fadeIn(speed);\r\n                }\r\n\r\n            }\r\n\r\n            else {\r\n                var s = plot.series[sidx];\r\n\r\n                if (s.canvas._elem.is(':hidden') || !s.show) {\r\n                    // Not sure if there is a better way to check for showSwatches and showLabels === true.\r\n                    // Test for \"undefined\" since default values for both showSwatches and showLables is true.\r\n                    if (typeof plot.options.legend.showSwatches === 'undefined' || plot.options.legend.showSwatches === true) {\r\n                        plot.legend._elem.find('td').eq(sidx * 2).addClass('jqplot-series-hidden');\r\n                    }\r\n                    if (typeof plot.options.legend.showLabels === 'undefined' || plot.options.legend.showLabels === true) {\r\n                        plot.legend._elem.find('td').eq((sidx * 2) + 1).addClass('jqplot-series-hidden');\r\n                    }\r\n                }\r\n                else {\r\n                    if (typeof plot.options.legend.showSwatches === 'undefined' || plot.options.legend.showSwatches === true) {\r\n                        plot.legend._elem.find('td').eq(sidx * 2).removeClass('jqplot-series-hidden');\r\n                    }\r\n                    if (typeof plot.options.legend.showLabels === 'undefined' || plot.options.legend.showLabels === true) {\r\n                        plot.legend._elem.find('td').eq((sidx * 2) + 1).removeClass('jqplot-series-hidden');\r\n                    }\r\n                }\r\n\r\n            }\r\n\r\n        };\r\n\r\n        s.toggleDisplay(ev, doLegendToggle);\r\n    };\r\n    \r\n    // called with scope of plot.\r\n    var postDraw = function () {\r\n        if (this.legend.renderer.constructor == $.jqplot.EnhancedLegendRenderer && this.legend.seriesToggle){\r\n            var e = this.legend._elem.detach();\r\n            this.eventCanvas._elem.after(e);\r\n        }\r\n    };\r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.enhancedPieLegendRenderer.js",
    "content": "/**\n * jqPlot\n * Pure JavaScript plotting plugin using jQuery\n *\n * Version: 1.0.9\n * Revision: d96a669\n *\n * Copyright (c) 2009-2016 Chris Leonello\n * jqPlot is currently available for use in all personal or commercial projects \n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \n * choose the license that best suits your project and use it accordingly. \n *\n * Although not required, the author would appreciate an email letting him \n * know of any substantial use of jqPlot.  You can reach the author at: \n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\n *\n * If you are feeling kind and generous, consider supporting the project by\n * making a donation at: http://www.jqplot.com/donate.php .\n *\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\n *\n *     version 2007.04.27\n *     author Ash Searle\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\n *     http://hexmen.com/js/sprintf.js\n *     The author (Ash Searle) has placed this code in the public domain:\n *     \"This code is unrestricted: you are free to use it however you like.\"\n * \n */\n(function($) {\n    // class $.jqplot.EnhancedPieLegendRenderer\n    // Legend renderer which can specify the number of rows and/or columns in the legend\n    // Similar to EnhancedLegendRenderer, but for pie charts\n    $.jqplot.EnhancedPieLegendRenderer = function(){\n        $.jqplot.TableLegendRenderer.call(this);\n    };\n    \n    $.jqplot.EnhancedPieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();\n    $.jqplot.EnhancedPieLegendRenderer.prototype.constructor = $.jqplot.EnhancedPieLegendRenderer;\n    \n    // called with scope of legend.\n    $.jqplot.EnhancedPieLegendRenderer.prototype.init = function(options) {\n        // prop: numberRows\n        // Maximum number of rows in the legend.  0 or null for unlimited.\n        this.numberRows = null;\n        // prop: numberColumns\n        // Maximum number of columns in the legend.  0 or null for unlimited.\n        this.numberColumns = null;\n        // prop: seriesToggle\n        // false to not enable series on/off toggling on the legend.\n        // true or a fadein/fadeout speed (number of milliseconds or 'fast', 'normal', 'slow') \n        // to enable show/hide of series on click of legend item.\n        this.seriesToggle = 'normal';\n        // prop: seriesToggleReplot\n        // True to replot the chart after toggling series on/off.\n        // This will set the series show property to false.\n        // This allows for rescaling or other maniplation of chart.\n        // Set to an options object (e.g. {resetAxes: true}) for replot options.\n        this.seriesToggleReplot = false;\n        // prop: disableIEFading\n        // true to toggle series with a show/hide method only and not allow fading in/out.  \n        // This is to overcome poor performance of fade in some versions of IE.\n        this.disableIEFading = true;\n        // prop: toolTips\n        // optional array of toolTip text corresponding to each pie slice\n        this.toolTips = [];\n        $.extend(true, this, options);\n        \n        if (this.seriesToggle) {\n            $.jqplot.postDrawHooks.push(postDraw);\n        }\n    };\n    \n    // called with scope of legend\n    $.jqplot.EnhancedPieLegendRenderer.prototype.draw = function(offsets, plot) {\n        var legend = this;\n        if (this.show) {\n            var series = this._series;\n            var s;\n            var ss = 'position:absolute;';\n            ss += (this.background) ? 'background:'+this.background+';' : '';\n            ss += (this.border) ? 'border:'+this.border+';' : '';\n            ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';\n            ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : '';\n            ss += (this.textColor) ? 'color:'+this.textColor+';' : '';\n            ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : '';\n            ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : '';\n            ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : '';\n            ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : '';\n            this._elem = $('<table class=\"jqplot-table-legend\" style=\"'+ss+'\"></table>');\n            if (this.seriesToggle) {\n                this._elem.css('z-index', '3');\n            }\n        \n            var pad = false, \n                reverse = false,\n                nr, nc;\n            var s = series[0];\n            var slen = s.data.length;\n            var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);\n\n            if (this.numberRows) {\n                nr = this.numberRows;\n                if (!this.numberColumns){\n                    nc = Math.ceil(slen/nr);\n                }\n                else{\n                    nc = this.numberColumns;\n                }\n            }\n            else if (this.numberColumns) {\n                nc = this.numberColumns;\n                nr = Math.ceil(slen/this.numberColumns);\n            }\n            else {\n                nr = slen;\n                nc = 1;\n            }\n                \n            var i, j, tr, td1, td2, lt, rs, div, div0, div1;\n            var idx = 0;\n            // check to see if we need to reverse\n            for (i=series.length-1; i>=0; i--) {\n                if (nc == 1 && series[i]._stack || series[i].renderer.constructor == $.jqplot.BezierCurveRenderer){\n                    reverse = true;\n                }\n            }    \n                \n            for (i=0; i<nr; i++) {\n                tr = $(document.createElement('tr'));\n                tr.addClass('jqplot-table-legend');\n                if (reverse){\n                    tr.prependTo(this._elem);\n                }\n                else{\n                    tr.appendTo(this._elem);\n                }\n                for (j=0; j<nc; j++) {\n                    if (idx < slen){\n                        lt = this.labels[idx] || s.data[idx][0].toString();\n                        tt = this.toolTips[idx];\n                        if (lt) {\n                            var color = colorGenerator.next();\n                            if (!reverse){\n                                if (i>0){\n                                    pad = true;\n                                }\n                                else{\n                                    pad = false;\n                                }\n                            }\n                            else{\n                                if (i == nr -1){\n                                    pad = false;\n                                }\n                                else{\n                                    pad = true;\n                                }\n                            }\n                            rs = (pad) ? this.rowSpacing : '0';\n\n                            td1 = $(document.createElement('td'));\n                            td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');\n                            td1.css({textAlign: 'center', paddingTop: rs});\n\n                            div0 = $(document.createElement('div'));\n                            div0.addClass('jqplot-table-legend-swatch-outline');\n                            if (tt !== undefined) {\n                                div0.attr(\"title\", tt);\n                            }\n\n                            div1 = $(document.createElement('div'));\n                            div1.addClass('jqplot-table-legend-swatch');\n                            div1.css({backgroundColor: color, borderColor: color});\n\n                            td1.append(div0.append(div1));\n\n                            td2 = $(document.createElement('td'));\n                            td2.addClass('jqplot-table-legend jqplot-table-legend-label');\n                            td2.css('paddingTop', rs);\n                            if (tt !== undefined) {\n                                td2.attr(\"title\", tt);\n                            }\n                    \n                            if (this.escapeHtml){\n                                td2.text(lt);\n                            }\n                            else {\n                                td2.html(lt);\n                            }\n                            if (reverse) {\n                                if (this.showLabels) {td2.prependTo(tr);}\n                                if (this.showSwatches) {td1.prependTo(tr);}\n                            }\n                            else {\n                                if (this.showSwatches) {td1.appendTo(tr);}\n                                if (this.showLabels) {td2.appendTo(tr);}\n                            }\n                            \n                            if (this.seriesToggle) {\n\n                                var speed;\n                                if (typeof(this.seriesToggle) === 'string' || typeof(this.seriesToggle) === 'number') {\n                                    if (!$.jqplot.use_excanvas || !this.disableIEFading) {\n                                        speed = this.seriesToggle;\n                                    }\n                                } \n                                if (this.showSwatches) {\n                                    td1.bind('click', {series:s, index:idx, speed:speed, plot: plot, replot:this.seriesToggleReplot}, handleToggle);\n                                    td1.addClass('jqplot-seriesToggle');\n                                }\n                                if (this.showLabels)  {\n                                    td2.bind('click', {series:s, index:idx, speed:speed, plot: plot, replot:this.seriesToggleReplot}, handleToggle);\n                                    td2.addClass('jqplot-seriesToggle');\n                                }\n\n                                // for slices that are already hidden, add the hidden class\n                                if (s.showSlice[idx] === false && s.showLabel) {\n                                    td1.addClass('jqplot-series-hidden');\n                                    td2.addClass('jqplot-series-hidden');\n                                }\n                            }\n                            \n                            pad = true;\n                        }\n                    }\n                    idx++;\n                }\n                \n                td1 = td2 = div0 = div1 = null;   \n            }\n        }\n        return this._elem;\n    };\n\n    var handleToggle = function (ev) {\n        var d = ev.data,\n            replot = d.replot,\n            plot = d.plot,\n            idx = d.index;\n\n        d.series.showSlice[idx] = (d.series.showSlice[idx] === false) ? true : false;\n    \n        var opts = {};\n\n        if ($.isPlainObject(replot)) {\n            $.extend(true, opts, replot);\n        }\n\n        plot.replot(opts);\n    };\n\n    // called with scope of plot.\n    var postDraw = function () {\n        if (this.legend.renderer.constructor == $.jqplot.EnhancedPieLegendRenderer && this.legend.seriesToggle) {\n            var e = this.legend._elem.detach();\n            this.eventCanvas._elem.after(e);\n        }\n    };\n})(jQuery);\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.funnelRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.FunnelRenderer\r\n     * Plugin renderer to draw a funnel chart.\r\n     * x values, if present, will be used as labels.\r\n     * y values give area size.\r\n     * \r\n     * Funnel charts will draw a single series\r\n     * only.\r\n     * \r\n     * To use this renderer, you need to include the \r\n     * funnel renderer plugin, for example:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.funnelRenderer.js\"></script>\r\n     * \r\n     * Properties described here are passed into the $.jqplot function\r\n     * as options on the series renderer.  For example:\r\n     * \r\n     * > plot2 = $.jqplot('chart2', [s1, s2], {\r\n     * >     seriesDefaults: {\r\n     * >         renderer:$.jqplot.FunnelRenderer,\r\n     * >         rendererOptions:{\r\n     * >              sectionMargin: 12,\r\n     * >              widthRatio: 0.3\r\n     * >          }\r\n     * >      }\r\n     * > });\r\n     * \r\n     * IMPORTANT\r\n     * \r\n     * *The funnel renderer will reorder data in descending order* so the largest value in\r\n     * the data set is first and displayed on top of the funnel.  Data will then\r\n     * be displayed in descending order down the funnel.  The area of each funnel\r\n     * section will correspond to the value of each data point relative to the sum\r\n     * of all values.  That is section area is proportional to section value divided by \r\n     * sum of all section values.\r\n     * \r\n     * If your data is not in descending order when passed into the plot, *it will be\r\n     * reordered* when stored in the series.data property.  A copy of the unordered\r\n     * data is kept in the series._unorderedData property.\r\n     * \r\n     * A funnel plot will trigger events on the plot target\r\n     * according to user interaction.  All events return the event object,\r\n     * the series index, the point (section) index, and the point data for \r\n     * the appropriate section. *Note* the point index will referr to the ordered\r\n     * data, not the original unordered data.\r\n     * \r\n     * 'jqplotDataMouseOver' - triggered when mousing over a section.\r\n     * 'jqplotDataHighlight' - triggered the first time user mouses over a section,\r\n     * if highlighting is enabled.\r\n     * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of\r\n     * a highlighted section.\r\n     * 'jqplotDataClick' - triggered when the user clicks on a section.\r\n     * 'jqplotDataRightClick' - tiggered when the user right clicks on a section if\r\n     * the \"captureRightClick\" option is set to true on the plot.\r\n     */\r\n    $.jqplot.FunnelRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.FunnelRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.FunnelRenderer.prototype.constructor = $.jqplot.FunnelRenderer;\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.FunnelRenderer.prototype.init = function(options, plot) {\r\n        // Group: Properties\r\n        //\r\n        // prop: padding\r\n        // padding between the funnel and plot edges, legend, etc.\r\n        this.padding = {top: 20, right: 20, bottom: 20, left: 20};\r\n        // prop: sectionMargin\r\n        // spacing between funnel sections in pixels.\r\n        this.sectionMargin = 6;\r\n        // prop: fill\r\n        // true or false, whether to fill the areas.\r\n        this.fill = true;\r\n        // prop: shadowOffset\r\n        // offset of the shadow from the area and offset of \r\n        // each succesive stroke of the shadow from the last.\r\n        this.shadowOffset = 2;\r\n        // prop: shadowAlpha\r\n        // transparency of the shadow (0 = transparent, 1 = opaque)\r\n        this.shadowAlpha = 0.07;\r\n        // prop: shadowDepth\r\n        // number of strokes to apply to the shadow, \r\n        // each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 5;\r\n        // prop: highlightMouseOver\r\n        // True to highlight area when moused over.\r\n        // This must be false to enable highlightMouseDown to highlight when clicking on a area.\r\n        this.highlightMouseOver = true;\r\n        // prop: highlightMouseDown\r\n        // True to highlight when a mouse button is pressed over a area.\r\n        // This will be disabled if highlightMouseOver is true.\r\n        this.highlightMouseDown = false;\r\n        // prop: highlightColors\r\n        // array of colors to use when highlighting an area.\r\n        this.highlightColors = [];\r\n        // prop: widthRatio\r\n        // The ratio of the width of the top of the funnel to the bottom.\r\n        // a ratio of 0 will make an upside down pyramid. \r\n        this.widthRatio = 0.2;\r\n        // prop: lineWidth\r\n        // width of line if areas are stroked and not filled.\r\n        this.lineWidth = 2;\r\n        // prop: dataLabels\r\n        // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices.\r\n        // Defaults to percentage of each pie slice.\r\n        this.dataLabels = 'percent';\r\n        // prop: showDataLabels\r\n        // true to show data labels on slices.\r\n        this.showDataLabels = false;\r\n        // prop: dataLabelFormatString\r\n        // Format string for data labels.  If none, '%s' is used for \"label\" and for arrays, '%d' for value and '%d%%' for percentage.\r\n        this.dataLabelFormatString = null;\r\n        // prop: dataLabelThreshold\r\n        // Threshhold in percentage (0 - 100) of pie area, below which no label will be displayed.\r\n        // This applies to all label types, not just to percentage labels.\r\n        this.dataLabelThreshold = 3;\r\n        this._type = 'funnel';\r\n        \r\n        this.tickRenderer = $.jqplot.FunnelTickRenderer;\r\n        \r\n        // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver\r\n        if (options.highlightMouseDown && options.highlightMouseOver == null) {\r\n            options.highlightMouseOver = false;\r\n        }\r\n        \r\n        $.extend(true, this, options);\r\n        \r\n        // index of the currenty highlighted point, if any\r\n        this._highlightedPoint = null;\r\n        \r\n        // lengths of bases, or horizontal sides of areas of trapezoid.\r\n        this._bases = [];\r\n        // total area\r\n        this._atot;\r\n        // areas of segments.\r\n        this._areas = [];\r\n        // vertical lengths of segments.\r\n        this._lengths = [];\r\n        // angle of the funnel to vertical.\r\n        this._angle;\r\n        this._dataIndices = [];\r\n        \r\n        // sort data\r\n        this._unorderedData = $.extend(true, [], this.data);\r\n        var idxs = $.extend(true, [], this.data);\r\n        for (var i=0; i<idxs.length; i++) {\r\n            idxs[i].push(i);\r\n        }\r\n        this.data.sort( function (a, b) { return b[1] - a[1]; } );\r\n        idxs.sort( function (a, b) { return b[1] - a[1]; });\r\n        for (var i=0; i<idxs.length; i++) {\r\n            this._dataIndices.push(idxs[i][2]);\r\n        }\r\n        \r\n        // set highlight colors if none provided\r\n        if (this.highlightColors.length == 0) {\r\n            for (var i=0; i<this.seriesColors.length; i++){\r\n                var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);\r\n                var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n                var sum = newrgb[0] + newrgb[1] + newrgb[2];\r\n                for (var j=0; j<3; j++) {\r\n                    // when darkening, lowest color component can be is 60.\r\n                    newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.4 * (255 - newrgb[j]);\r\n                    newrgb[j] = parseInt(newrgb[j], 10);\r\n                }\r\n                this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');\r\n            }\r\n        }\r\n\r\n        plot.postParseOptionsHooks.addOnce(postParseOptions);\r\n        plot.postInitHooks.addOnce(postInit);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);\r\n        plot.eventListenerHooks.addOnce('jqplotClick', handleClick);\r\n        plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);\r\n        plot.postDrawHooks.addOnce(postPlotDraw);        \r\n        \r\n    };\r\n    \r\n    // gridData will be of form [label, percentage of total]\r\n    $.jqplot.FunnelRenderer.prototype.setGridData = function(plot) {\r\n        // set gridData property.  This will hold angle in radians of each data point.\r\n        var sum = 0;\r\n        var td = [];\r\n        for (var i=0; i<this.data.length; i++){\r\n            sum += this.data[i][1];\r\n            td.push([this.data[i][0], this.data[i][1]]);\r\n        }\r\n        \r\n        // normalize y values, so areas are proportional.\r\n        for (var i=0; i<td.length; i++) {\r\n            td[i][1] = td[i][1]/sum;\r\n        }\r\n        \r\n        this._bases = new Array(td.length + 1);\r\n        this._lengths = new Array(td.length);\r\n        \r\n        this.gridData = td;\r\n    };\r\n    \r\n    $.jqplot.FunnelRenderer.prototype.makeGridData = function(data, plot) {\r\n        // set gridData property.  This will hold angle in radians of each data point.\r\n        var sum = 0;\r\n        var td = [];\r\n        for (var i=0; i<this.data.length; i++){\r\n            sum += this.data[i][1];\r\n            td.push([this.data[i][0], this.data[i][1]]);\r\n        }\r\n        \r\n        // normalize y values, so areas are proportional.\r\n        for (var i=0; i<td.length; i++) {\r\n            td[i][1] = td[i][1]/sum;\r\n        }\r\n        \r\n        this._bases = new Array(td.length + 1);\r\n        this._lengths = new Array(td.length);\r\n        \r\n        return td;\r\n    };\r\n    \r\n    $.jqplot.FunnelRenderer.prototype.drawSection = function (ctx, vertices, color, isShadow) {\r\n        var fill = this.fill;\r\n        var lineWidth = this.lineWidth;\r\n        ctx.save();\r\n        \r\n        if (isShadow) {\r\n            for (var i=0; i<this.shadowDepth; i++) {\r\n                ctx.save();\r\n                ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));\r\n                doDraw();\r\n            }\r\n        }\r\n        \r\n        else {\r\n            doDraw();\r\n        }\r\n        \r\n        function doDraw () {\r\n            ctx.beginPath();  \r\n            ctx.fillStyle = color;\r\n            ctx.strokeStyle = color;\r\n            ctx.lineWidth = lineWidth;\r\n            ctx.moveTo(vertices[0][0], vertices[0][1]);\r\n            for (var i=1; i<4; i++) {\r\n                ctx.lineTo(vertices[i][0], vertices[i][1]);\r\n            }\r\n            ctx.closePath();\r\n            if (fill) {\r\n                ctx.fill();\r\n            }\r\n            else {\r\n                ctx.stroke();\r\n            }\r\n        }\r\n        \r\n        if (isShadow) {\r\n            for (var i=0; i<this.shadowDepth; i++) {\r\n                ctx.restore();\r\n            }\r\n        }\r\n        \r\n        ctx.restore();\r\n    };\r\n    \r\n    // called with scope of series\r\n    $.jqplot.FunnelRenderer.prototype.draw = function (ctx, gd, options, plot) {\r\n        var i;\r\n        var opts = (options != undefined) ? options : {};\r\n        // offset and direction of offset due to legend placement\r\n        var offx = 0;\r\n        var offy = 0;\r\n        var trans = 1;\r\n        this._areas = [];\r\n        // var colorGenerator = new this.colorGenerator(this.seriesColors);\r\n        if (options.legendInfo && options.legendInfo.placement == 'insideGrid') {\r\n            var li = options.legendInfo;\r\n            switch (li.location) {\r\n                case 'nw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'w':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'sw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'ne':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'e':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'se':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'n':\r\n                    offy = li.height + li.yoffset;\r\n                    break;\r\n                case 's':\r\n                    offy = li.height + li.yoffset;\r\n                    trans = -1;\r\n                    break;\r\n                default:\r\n                    break;\r\n            }\r\n        }\r\n        \r\n        var loff = (trans==1) ? this.padding.left + offx : this.padding.left;\r\n        var toff = (trans==1) ? this.padding.top + offy : this.padding.top;\r\n        var roff = (trans==-1) ? this.padding.right + offx : this.padding.right;\r\n        var boff = (trans==-1) ? this.padding.bottom + offy : this.padding.bottom;\r\n        \r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        var cw = ctx.canvas.width;\r\n        var ch = ctx.canvas.height;\r\n        this._bases[0] = cw - loff - roff;\r\n        var ltot = this._length = ch - toff - boff;\r\n\r\n        var hend = this._bases[0]*this.widthRatio;\r\n        this._atot = ltot/2 * (this._bases[0] + this._bases[0]*this.widthRatio);\r\n\r\n        this._angle = Math.atan((this._bases[0] - hend)/2/ltot);\r\n\r\n        for (i=0; i<gd.length; i++) {\r\n            this._areas.push(gd[i][1] * this._atot);\r\n        }\r\n\r\n        \r\n        var guess, err, count, lsum=0;\r\n        var tolerance = 0.0001;\r\n\r\n        for (i=0; i<this._areas.length; i++) {\r\n            guess = this._areas[i]/this._bases[i];\r\n            err = 999999;\r\n            this._lengths[i] = guess;\r\n            count = 0;\r\n            while (err > this._lengths[i]*tolerance && count < 100) {\r\n                this._lengths[i] = this._areas[i]/(this._bases[i] - this._lengths[i] * Math.tan(this._angle));\r\n                err = Math.abs(this._lengths[i] - guess);\r\n                this._bases[i+1] = this._bases[i] - (2*this._lengths[i]*Math.tan(this._angle));\r\n                guess = this._lengths[i];\r\n                count++;\r\n            }\r\n            lsum += this._lengths[i];\r\n        }\r\n        \r\n        // figure out vertices of each section\r\n        this._vertices = new Array(gd.length);\r\n        \r\n        // these are 4 coners of entire trapezoid\r\n        var p0 = [loff, toff],\r\n            p1 = [loff+this._bases[0], toff],\r\n            p2 = [loff + (this._bases[0] - this._bases[this._bases.length-1])/2, toff + this._length],\r\n            p3 = [p2[0] + this._bases[this._bases.length-1], p2[1]];\r\n            \r\n        // equations of right and left sides, returns x, y values given height of section (y value)\r\n        function findleft (l) {\r\n            var m = (p0[1] - p2[1])/(p0[0] - p2[0]);\r\n            var b = p0[1] - m*p0[0];\r\n            var y = l + p0[1];\r\n            \r\n            return [(y - b)/m, y];\r\n        }\r\n        \r\n        function findright (l) {\r\n            var m = (p1[1] - p3[1])/(p1[0] - p3[0]);\r\n            var b = p1[1] - m*p1[0];\r\n            var y = l + p1[1];\r\n            \r\n            return [(y - b)/m, y];\r\n        }\r\n        \r\n        var x = offx, y = offy;\r\n        var h=0, adj=0;\r\n        \r\n        for (i=0; i<gd.length; i++) {\r\n            this._vertices[i] = new Array();\r\n            var v = this._vertices[i];\r\n            var sm = this.sectionMargin;\r\n            if (i == 0) {\r\n                adj = 0;\r\n            }\r\n            if (i == 1) {\r\n                adj = sm/3;\r\n            }\r\n            else if (i > 0 && i < gd.length-1) {\r\n                adj = sm/2;\r\n            }\r\n            else if (i == gd.length -1) {\r\n                adj = 2*sm/3;\r\n            }\r\n            v.push(findleft(h+adj));\r\n            v.push(findright(h+adj));\r\n            h += this._lengths[i];\r\n            if (i == 0) {\r\n                adj = -2*sm/3;\r\n            }\r\n            else if (i > 0 && i < gd.length-1) {\r\n                adj = -sm/2;\r\n            }\r\n            else if (i == gd.length - 1) {\r\n                adj = 0;\r\n            }\r\n            v.push(findright(h+adj));\r\n            v.push(findleft(h+adj));\r\n            \r\n        }\r\n\r\n        if (this.shadow) {\r\n            var shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';\r\n            for (var i=0; i<gd.length; i++) {\r\n                this.renderer.drawSection.call (this, ctx, this._vertices[i], shadowColor, true);\r\n            }\r\n            \r\n        }\r\n        for (var i=0; i<gd.length; i++) {\r\n            var v = this._vertices[i];\r\n            this.renderer.drawSection.call (this, ctx, v, this.seriesColors[i]);\r\n            \r\n            if (this.showDataLabels && gd[i][1]*100 >= this.dataLabelThreshold) {\r\n                var fstr, label;\r\n                \r\n                if (this.dataLabels == 'label') {\r\n                    fstr = this.dataLabelFormatString || '%s';\r\n                    label = $.jqplot.sprintf(fstr, gd[i][0]);\r\n                }\r\n                else if (this.dataLabels == 'value') {\r\n                    fstr = this.dataLabelFormatString || '%d';\r\n                    label = $.jqplot.sprintf(fstr, this.data[i][1]);\r\n                }\r\n                else if (this.dataLabels == 'percent') {\r\n                    fstr = this.dataLabelFormatString || '%d%%';\r\n                    label = $.jqplot.sprintf(fstr, gd[i][1]*100);\r\n                }\r\n                else if (this.dataLabels.constructor == Array) {\r\n                    fstr = this.dataLabelFormatString || '%s';\r\n                    label = $.jqplot.sprintf(fstr, this.dataLabels[this._dataIndices[i]]);\r\n                }\r\n                \r\n                var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;\r\n                \r\n                var x = (v[0][0] + v[1][0])/2 + this.canvas._offsets.left;\r\n                var y = (v[1][1] + v[2][1])/2 + this.canvas._offsets.top;\r\n                \r\n                var labelelem = $('<span class=\"jqplot-funnel-series jqplot-data-label\" style=\"position:absolute;\">' + label + '</span>').insertBefore(plot.eventCanvas._elem);\r\n                x -= labelelem.width()/2;\r\n                y -= labelelem.height()/2;\r\n                x = Math.round(x);\r\n                y = Math.round(y);\r\n                labelelem.css({left: x, top: y});\r\n            }\r\n            \r\n        }\r\n               \r\n    };\r\n    \r\n    $.jqplot.FunnelAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.FunnelAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.FunnelAxisRenderer.prototype.constructor = $.jqplot.FunnelAxisRenderer;\r\n        \r\n    \r\n    // There are no traditional axes on a funnel chart.  We just need to provide\r\n    // dummy objects with properties so the plot will render.\r\n    // called with scope of axis object.\r\n    $.jqplot.FunnelAxisRenderer.prototype.init = function(options){\r\n        //\r\n        this.tickRenderer = $.jqplot.FunnelTickRenderer;\r\n        $.extend(true, this, options);\r\n        // I don't think I'm going to need _dataBounds here.\r\n        // have to go Axis scaling in a way to fit chart onto plot area\r\n        // and provide u2p and p2u functionality for mouse cursor, etc.\r\n        // for convienence set _dataBounds to 0 and 100 and\r\n        // set min/max to 0 and 100.\r\n        this._dataBounds = {min:0, max:100};\r\n        this.min = 0;\r\n        this.max = 100;\r\n        this.showTicks = false;\r\n        this.ticks = [];\r\n        this.showMark = false;\r\n        this.show = false; \r\n    };\r\n    \r\n    \r\n    \r\n    /**\r\n     * Class: $.jqplot.FunnelLegendRenderer\r\n     * Legend Renderer specific to funnel plots.  Set by default\r\n     * when the user creates a funnel plot.\r\n     */\r\n    $.jqplot.FunnelLegendRenderer = function(){\r\n        $.jqplot.TableLegendRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.FunnelLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();\r\n    $.jqplot.FunnelLegendRenderer.prototype.constructor = $.jqplot.FunnelLegendRenderer;\r\n    \r\n    $.jqplot.FunnelLegendRenderer.prototype.init = function(options) {\r\n        // Group: Properties\r\n        //\r\n        // prop: numberRows\r\n        // Maximum number of rows in the legend.  0 or null for unlimited.\r\n        this.numberRows = null;\r\n        // prop: numberColumns\r\n        // Maximum number of columns in the legend.  0 or null for unlimited.\r\n        this.numberColumns = null;\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    // called with context of legend\r\n    $.jqplot.FunnelLegendRenderer.prototype.draw = function() {\r\n        var legend = this;\r\n        if (this.show) {\r\n            var series = this._series;\r\n            var ss = 'position:absolute;';\r\n            ss += (this.background) ? 'background:'+this.background+';' : '';\r\n            ss += (this.border) ? 'border:'+this.border+';' : '';\r\n            ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';\r\n            ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : '';\r\n            ss += (this.textColor) ? 'color:'+this.textColor+';' : '';\r\n            ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : '';\r\n            ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : '';\r\n            ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : '';\r\n            ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : '';\r\n            this._elem = $('<table class=\"jqplot-table-legend\" style=\"'+ss+'\"></table>');\r\n            // Funnel charts legends don't go by number of series, but by number of data points\r\n            // in the series.  Refactor things here for that.\r\n            \r\n            var pad = false, \r\n                reverse = false,\r\n                nr, nc;\r\n            var s = series[0];\r\n            var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);\r\n            \r\n            if (s.show) {\r\n                var pd = s.data;\r\n                if (this.numberRows) {\r\n                    nr = this.numberRows;\r\n                    if (!this.numberColumns){\r\n                        nc = Math.ceil(pd.length/nr);\r\n                    }\r\n                    else{\r\n                        nc = this.numberColumns;\r\n                    }\r\n                }\r\n                else if (this.numberColumns) {\r\n                    nc = this.numberColumns;\r\n                    nr = Math.ceil(pd.length/this.numberColumns);\r\n                }\r\n                else {\r\n                    nr = pd.length;\r\n                    nc = 1;\r\n                }\r\n                \r\n                var i, j, tr, td1, td2, lt, rs, color;\r\n                var idx = 0;    \r\n                \r\n                for (i=0; i<nr; i++) {\r\n                    if (reverse){\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').prependTo(this._elem);\r\n                    }\r\n                    else{\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').appendTo(this._elem);\r\n                    }\r\n                    for (j=0; j<nc; j++) {\r\n                        if (idx < pd.length){\r\n                            lt = this.labels[idx] || pd[idx][0].toString();\r\n                            color = colorGenerator.next();\r\n                            if (!reverse){\r\n                                if (i>0){\r\n                                    pad = true;\r\n                                }\r\n                                else{\r\n                                    pad = false;\r\n                                }\r\n                            }\r\n                            else{\r\n                                if (i == nr -1){\r\n                                    pad = false;\r\n                                }\r\n                                else{\r\n                                    pad = true;\r\n                                }\r\n                            }\r\n                            rs = (pad) ? this.rowSpacing : '0';\r\n                \r\n                            td1 = $('<td class=\"jqplot-table-legend\" style=\"text-align:center;padding-top:'+rs+';\">'+\r\n                                '<div><div class=\"jqplot-table-legend-swatch\" style=\"border-color:'+color+';\"></div>'+\r\n                                '</div></td>');\r\n                            td2 = $('<td class=\"jqplot-table-legend\" style=\"padding-top:'+rs+';\"></td>');\r\n                            if (this.escapeHtml){\r\n                                td2.text(lt);\r\n                            }\r\n                            else {\r\n                                td2.html(lt);\r\n                            }\r\n                            if (reverse) {\r\n                                td2.prependTo(tr);\r\n                                td1.prependTo(tr);\r\n                            }\r\n                            else {\r\n                                td1.appendTo(tr);\r\n                                td2.appendTo(tr);\r\n                            }\r\n                            pad = true;\r\n                        }\r\n                        idx++;\r\n                    }   \r\n                }\r\n            }\r\n        }\r\n        return this._elem;                \r\n    };\r\n    \r\n    // $.jqplot.FunnelLegendRenderer.prototype.pack = function(offsets) {\r\n    //     if (this.show) {\r\n    //         // fake a grid for positioning\r\n    //         var grid = {_top:offsets.top, _left:offsets.left, _right:offsets.right, _bottom:this._plotDimensions.height - offsets.bottom};        \r\n    //         if (this.placement == 'insideGrid') {\r\n    //             switch (this.location) {\r\n    //                 case 'nw':\r\n    //                     var a = grid._left + this.xoffset;\r\n    //                     var b = grid._top + this.yoffset;\r\n    //                     this._elem.css('left', a);\r\n    //                     this._elem.css('top', b);\r\n    //                     break;\r\n    //                 case 'n':\r\n    //                     var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n    //                     var b = grid._top + this.yoffset;\r\n    //                     this._elem.css('left', a);\r\n    //                     this._elem.css('top', b);\r\n    //                     break;\r\n    //                 case 'ne':\r\n    //                     var a = offsets.right + this.xoffset;\r\n    //                     var b = grid._top + this.yoffset;\r\n    //                     this._elem.css({right:a, top:b});\r\n    //                     break;\r\n    //                 case 'e':\r\n    //                     var a = offsets.right + this.xoffset;\r\n    //                     var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n    //                     this._elem.css({right:a, top:b});\r\n    //                     break;\r\n    //                 case 'se':\r\n    //                     var a = offsets.right + this.xoffset;\r\n    //                     var b = offsets.bottom + this.yoffset;\r\n    //                     this._elem.css({right:a, bottom:b});\r\n    //                     break;\r\n    //                 case 's':\r\n    //                     var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n    //                     var b = offsets.bottom + this.yoffset;\r\n    //                     this._elem.css({left:a, bottom:b});\r\n    //                     break;\r\n    //                 case 'sw':\r\n    //                     var a = grid._left + this.xoffset;\r\n    //                     var b = offsets.bottom + this.yoffset;\r\n    //                     this._elem.css({left:a, bottom:b});\r\n    //                     break;\r\n    //                 case 'w':\r\n    //                     var a = grid._left + this.xoffset;\r\n    //                     var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n    //                     this._elem.css({left:a, top:b});\r\n    //                     break;\r\n    //                 default:  // same as 'se'\r\n    //                     var a = grid._right - this.xoffset;\r\n    //                     var b = grid._bottom + this.yoffset;\r\n    //                     this._elem.css({right:a, bottom:b});\r\n    //                     break;\r\n    //             }\r\n    //             \r\n    //         }\r\n    //         else {\r\n    //             switch (this.location) {\r\n    //                 case 'nw':\r\n    //                     var a = this._plotDimensions.width - grid._left + this.xoffset;\r\n    //                     var b = grid._top + this.yoffset;\r\n    //                     this._elem.css('right', a);\r\n    //                     this._elem.css('top', b);\r\n    //                     break;\r\n    //                 case 'n':\r\n    //                     var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n    //                     var b = this._plotDimensions.height - grid._top + this.yoffset;\r\n    //                     this._elem.css('left', a);\r\n    //                     this._elem.css('bottom', b);\r\n    //                     break;\r\n    //                 case 'ne':\r\n    //                     var a = this._plotDimensions.width - offsets.right + this.xoffset;\r\n    //                     var b = grid._top + this.yoffset;\r\n    //                     this._elem.css({left:a, top:b});\r\n    //                     break;\r\n    //                 case 'e':\r\n    //                     var a = this._plotDimensions.width - offsets.right + this.xoffset;\r\n    //                     var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n    //                     this._elem.css({left:a, top:b});\r\n    //                     break;\r\n    //                 case 'se':\r\n    //                     var a = this._plotDimensions.width - offsets.right + this.xoffset;\r\n    //                     var b = offsets.bottom + this.yoffset;\r\n    //                     this._elem.css({left:a, bottom:b});\r\n    //                     break;\r\n    //                 case 's':\r\n    //                     var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n    //                     var b = this._plotDimensions.height - offsets.bottom + this.yoffset;\r\n    //                     this._elem.css({left:a, top:b});\r\n    //                     break;\r\n    //                 case 'sw':\r\n    //                     var a = this._plotDimensions.width - grid._left + this.xoffset;\r\n    //                     var b = offsets.bottom + this.yoffset;\r\n    //                     this._elem.css({right:a, bottom:b});\r\n    //                     break;\r\n    //                 case 'w':\r\n    //                     var a = this._plotDimensions.width - grid._left + this.xoffset;\r\n    //                     var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n    //                     this._elem.css({right:a, top:b});\r\n    //                     break;\r\n    //                 default:  // same as 'se'\r\n    //                     var a = grid._right - this.xoffset;\r\n    //                     var b = grid._bottom + this.yoffset;\r\n    //                     this._elem.css({right:a, bottom:b});\r\n    //                     break;\r\n    //             }\r\n    //         }\r\n    //     } \r\n    // };\r\n    \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        options = options || {};\r\n        options.axesDefaults = options.axesDefaults || {};\r\n        options.legend = options.legend || {};\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        // only set these if there is a funnel series\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer == $.jqplot.FunnelRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer == $.jqplot.FunnelRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.FunnelAxisRenderer;\r\n            options.legend.renderer = $.jqplot.FunnelLegendRenderer;\r\n            options.legend.preDraw = true;\r\n            options.sortData = false;\r\n            options.seriesDefaults.pointLabels = {show: false};\r\n        }\r\n    }\r\n    \r\n    function postInit(target, data, options) {\r\n        // if multiple series, add a reference to the previous one so that\r\n        // funnel rings can nest.\r\n        for (var i=0; i<this.series.length; i++) {\r\n            if (this.series[i].renderer.constructor == $.jqplot.FunnelRenderer) {\r\n                // don't allow mouseover and mousedown at same time.\r\n                if (this.series[i].highlightMouseOver) {\r\n                    this.series[i].highlightMouseDown = false;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    \r\n    // called with scope of plot\r\n    function postParseOptions(options) {\r\n        for (var i=0; i<this.series.length; i++) {\r\n            this.series[i].seriesColors = this.seriesColors;\r\n            this.series[i].colorGenerator = $.jqplot.colorGenerator;\r\n        }\r\n    }\r\n    \r\n    function highlight (plot, sidx, pidx) {\r\n        var s = plot.series[sidx];\r\n        var canvas = plot.plugins.funnelRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        s._highlightedPoint = pidx;\r\n        plot.plugins.funnelRenderer.highlightedSeriesIndex = sidx;\r\n        s.renderer.drawSection.call(s, canvas._ctx, s._vertices[pidx], s.highlightColors[pidx], false);\r\n    }\r\n    \r\n    function unhighlight (plot) {\r\n        var canvas = plot.plugins.funnelRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            plot.series[i]._highlightedPoint = null;\r\n        }\r\n        plot.plugins.funnelRenderer.highlightedSeriesIndex = null;\r\n        plot.target.trigger('jqplotDataUnhighlight');\r\n    }\r\n    \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt1 = jQuery.Event('jqplotDataMouseOver');\r\n            evt1.pageX = ev.pageX;\r\n            evt1.pageY = ev.pageY;\r\n            plot.target.trigger(evt1, ins);\r\n            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.funnelRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {\r\n        var idx = plot.plugins.funnelRenderer.highlightedSeriesIndex;\r\n        if (idx != null && plot.series[idx].highlightMouseDown) {\r\n            unhighlight(plot);\r\n        }\r\n    }\r\n    \r\n    function handleClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt = jQuery.Event('jqplotDataClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var idx = plot.plugins.funnelRenderer.highlightedSeriesIndex;\r\n            if (idx != null && plot.series[idx].highlightMouseDown) {\r\n                unhighlight(plot);\r\n            }\r\n            var evt = jQuery.Event('jqplotDataRightClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    function postPlotDraw() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.funnelRenderer && this.plugins.funnelRenderer.highlightCanvas) {\r\n            this.plugins.funnelRenderer.highlightCanvas.resetCanvas();\r\n            this.plugins.funnelRenderer.highlightCanvas = null;\r\n        }\r\n\r\n        this.plugins.funnelRenderer = {};\r\n        this.plugins.funnelRenderer.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        \r\n        // do we have any data labels?  if so, put highlight canvas before those\r\n        var labels = $(this.targetId+' .jqplot-data-label');\r\n        if (labels.length) {\r\n            $(labels[0]).before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-funnelRenderer-highlight-canvas', this._plotDimensions, this));\r\n        }\r\n        // else put highlight canvas before event canvas.\r\n        else {\r\n            this.eventCanvas._elem.before(this.plugins.funnelRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-funnelRenderer-highlight-canvas', this._plotDimensions, this));\r\n        }\r\n        var hctx = this.plugins.funnelRenderer.highlightCanvas.setContext();\r\n        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });\r\n    }\r\n    \r\n    $.jqplot.preInitHooks.push(preInit);\r\n    \r\n    $.jqplot.FunnelTickRenderer = function() {\r\n        $.jqplot.AxisTickRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.FunnelTickRenderer.prototype = new $.jqplot.AxisTickRenderer();\r\n    $.jqplot.FunnelTickRenderer.prototype.constructor = $.jqplot.FunnelTickRenderer;\r\n    \r\n})(jQuery);\r\n    \r\n    "
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.highlighter.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]);\r\n    \r\n    /**\r\n     * Class: $.jqplot.Highlighter\r\n     * Plugin which will highlight data points when they are moused over.\r\n     * \r\n     * To use this plugin, include the js\r\n     * file in your source:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.highlighter.js\"></script>\r\n     * \r\n     * A tooltip providing information about the data point is enabled by default.\r\n     * To disable the tooltip, set \"showTooltip\" to false.\r\n     * \r\n     * You can control what data is displayed in the tooltip with various\r\n     * options.  The \"tooltipAxes\" option controls whether the x, y or both\r\n     * data values are displayed.\r\n     * \r\n     * Some chart types (e.g. hi-low-close) have more than one y value per\r\n     * data point. To display the additional values in the tooltip, set the\r\n     * \"yvalues\" option to the desired number of y values present (3 for a hlc chart).\r\n     * \r\n     * By default, data values will be formatted with the same formatting\r\n     * specifiers as used to format the axis ticks.  A custom format code\r\n     * can be supplied with the tooltipFormatString option.  This will apply \r\n     * to all values in the tooltip.  \r\n     * \r\n     * For more complete control, the \"formatString\" option can be set.  This\r\n     * Allows conplete control over tooltip formatting.  Values are passed to\r\n     * the format string in an order determined by the \"tooltipAxes\" and \"yvalues\"\r\n     * options.  So, if you have a hi-low-close chart and you just want to display \r\n     * the hi-low-close values in the tooltip, you could set a formatString like:\r\n     * \r\n     * > highlighter: {\r\n     * >     tooltipAxes: 'y',\r\n     * >     yvalues: 3,\r\n     * >     formatString:'<table class=\"jqplot-highlighter\">\r\n     * >         <tr><td>hi:</td><td>%s</td></tr>\r\n     * >         <tr><td>low:</td><td>%s</td></tr>\r\n     * >         <tr><td>close:</td><td>%s</td></tr></table>'\r\n     * > }\r\n     * \r\n     */\r\n    $.jqplot.Highlighter = function(options) {\r\n        // Group: Properties\r\n        //\r\n        //prop: show\r\n        // true to show the highlight.\r\n        this.show = $.jqplot.config.enablePlugins;\r\n        // prop: markerRenderer\r\n        // Renderer used to draw the marker of the highlighted point.\r\n        // Renderer will assimilate attributes from the data point being highlighted,\r\n        // so no attributes need set on the renderer directly.\r\n        // Default is to turn off shadow drawing on the highlighted point.\r\n        this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false});\r\n        // prop: showMarker\r\n        // true to show the marker\r\n        this.showMarker  = true;\r\n        // prop: lineWidthAdjust\r\n        // Pixels to add to the lineWidth of the highlight.\r\n        this.lineWidthAdjust = 2.5;\r\n        // prop: sizeAdjust\r\n        // Pixels to add to the overall size of the highlight.\r\n        this.sizeAdjust = 5;\r\n        // prop: showTooltip\r\n        // Show a tooltip with data point values.\r\n        this.showTooltip = true;\r\n        // prop: tooltipLocation\r\n        // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'\r\n        this.tooltipLocation = 'nw';\r\n        // prop: fadeTooltip\r\n        // true = fade in/out tooltip, flase = show/hide tooltip\r\n        this.fadeTooltip = true;\r\n        // prop: tooltipFadeSpeed\r\n        // 'slow', 'def', 'fast', or number of milliseconds.\r\n        this.tooltipFadeSpeed = \"fast\";\r\n        // prop: tooltipOffset\r\n        // Pixel offset of tooltip from the highlight.\r\n        this.tooltipOffset = 2;\r\n        // prop: tooltipAxes\r\n        // Which axes to display in tooltip, 'x', 'y' or 'both', 'xy' or 'yx'\r\n        // 'both' and 'xy' are equivalent, 'yx' reverses order of labels.\r\n        this.tooltipAxes = 'both';\r\n        // prop; tooltipSeparator\r\n        // String to use to separate x and y axes in tooltip.\r\n        this.tooltipSeparator = ', ';\r\n        // prop; tooltipContentEditor\r\n        // Function used to edit/augment/replace the formatted tooltip contents.\r\n        // Called as str = tooltipContentEditor(str, seriesIndex, pointIndex)\r\n        // where str is the generated tooltip html and seriesIndex and pointIndex identify\r\n        // the data point being highlighted. Should return the html for the tooltip contents.\r\n        this.tooltipContentEditor = null;\r\n        // prop: useAxesFormatters\r\n        // Use the x and y axes formatters to format the text in the tooltip.\r\n        this.useAxesFormatters = true;\r\n        // prop: tooltipFormatString\r\n        // sprintf format string for the tooltip.\r\n        // Uses Ash Searle's javascript sprintf implementation\r\n        // found here: http://hexmen.com/blog/2007/03/printf-sprintf/\r\n        // See http://perldoc.perl.org/functions/sprintf.html for reference.\r\n        // Additional \"p\" and \"P\" format specifiers added by Chris Leonello.\r\n        this.tooltipFormatString = '%.5P';\r\n        // prop: formatString\r\n        // alternative to tooltipFormatString\r\n        // will format the whole tooltip text, populating with x, y values as\r\n        // indicated by tooltipAxes option.  So, you could have a tooltip like:\r\n        // 'Date: %s, number of cats: %d' to format the whole tooltip at one go.\r\n        // If useAxesFormatters is true, values will be formatted according to\r\n        // Axes formatters and you can populate your tooltip string with \r\n        // %s placeholders.\r\n        this.formatString = null;\r\n        // prop: yvalues\r\n        // Number of y values to expect in the data point array.\r\n        // Typically this is 1.  Certain plots, like OHLC, will\r\n        // have more y values in each data point array.\r\n        this.yvalues = 1;\r\n        // prop: bringSeriesToFront\r\n        // This option requires jQuery 1.4+\r\n        // True to bring the series of the highlighted point to the front\r\n        // of other series.\r\n        this.bringSeriesToFront = false;\r\n        this._tooltipElem;\r\n        this.isHighlighting = false;\r\n        this.currentNeighbor = null;\r\n\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    var locations = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'];\r\n    var locationIndicies = {'nw':0, 'n':1, 'ne':2, 'e':3, 'se':4, 's':5, 'sw':6, 'w':7};\r\n    var oppositeLocations = ['se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'];\r\n    \r\n    // axis.renderer.tickrenderer.formatter\r\n    \r\n    // called with scope of plot\r\n    $.jqplot.Highlighter.init = function (target, data, opts){\r\n        var options = opts || {};\r\n        // add a highlighter attribute to the plot\r\n        this.plugins.highlighter = new $.jqplot.Highlighter(options.highlighter);\r\n    };\r\n    \r\n    // called within scope of series\r\n    $.jqplot.Highlighter.parseOptions = function (defaults, options) {\r\n        // Add a showHighlight option to the series \r\n        // and set it to true by default.\r\n        this.showHighlight = true;\r\n    };\r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    $.jqplot.Highlighter.postPlotDraw = function() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.highlighter && this.plugins.highlighter.highlightCanvas) {\r\n            this.plugins.highlighter.highlightCanvas.resetCanvas();\r\n            this.plugins.highlighter.highlightCanvas = null;\r\n        }\r\n\r\n        if (this.plugins.highlighter && this.plugins.highlighter._tooltipElem) {\r\n            this.plugins.highlighter._tooltipElem.emptyForce();\r\n            this.plugins.highlighter._tooltipElem = null;\r\n        }\r\n\r\n        this.plugins.highlighter.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        \r\n        this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding, 'jqplot-highlight-canvas', this._plotDimensions, this));\r\n        this.plugins.highlighter.highlightCanvas.setContext();\r\n\r\n        var elem = document.createElement('div');\r\n        this.plugins.highlighter._tooltipElem = $(elem);\r\n        elem = null;\r\n        this.plugins.highlighter._tooltipElem.addClass('jqplot-highlighter-tooltip');\r\n        this.plugins.highlighter._tooltipElem.css({position:'absolute', display:'none'});\r\n        \r\n        this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem);\r\n    };\r\n    \r\n    $.jqplot.preInitHooks.push($.jqplot.Highlighter.init);\r\n    $.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Highlighter.parseOptions);\r\n    $.jqplot.postDrawHooks.push($.jqplot.Highlighter.postPlotDraw);\r\n    \r\n    function draw(plot, neighbor) {\r\n        var hl = plot.plugins.highlighter;\r\n        var s = plot.series[neighbor.seriesIndex];\r\n        var smr = s.markerRenderer;\r\n        var mr = hl.markerRenderer;\r\n        mr.style = smr.style;\r\n        mr.lineWidth = smr.lineWidth + hl.lineWidthAdjust;\r\n        mr.size = smr.size + hl.sizeAdjust;\r\n        var rgba = $.jqplot.getColorComponents(smr.color);\r\n        var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n        var alpha = (rgba[3] >= 0.6) ? rgba[3]*0.6 : rgba[3]*(2-rgba[3]);\r\n        mr.color = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+alpha+')';\r\n        mr.init();\r\n        mr.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], hl.highlightCanvas._ctx);\r\n    }\r\n    \r\n    function showTooltip(plot, series, neighbor) {\r\n        // neighbor looks like: {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}\r\n        // gridData should be x,y pixel coords on the grid.\r\n        // add the plot._gridPadding to that to get x,y in the target.\r\n        var hl = plot.plugins.highlighter;\r\n        var elem = hl._tooltipElem;\r\n        var serieshl = series.highlighter || {};\r\n\r\n        var opts = $.extend(true, {}, hl, serieshl);\r\n\r\n        if (opts.useAxesFormatters) {\r\n            var xf = series._xaxis._ticks[0].formatter;\r\n            var yf = series._yaxis._ticks[0].formatter;\r\n            var xfstr = series._xaxis._ticks[0].formatString;\r\n            var yfstr = series._yaxis._ticks[0].formatString;\r\n            var str;\r\n            var xstr = xf(xfstr, neighbor.data[0]);\r\n            var ystrs = [];\r\n            for (var i=1; i<opts.yvalues+1; i++) {\r\n                ystrs.push(yf(yfstr, neighbor.data[i]));\r\n            }\r\n            if (typeof opts.formatString === 'string') {\r\n                switch (opts.tooltipAxes) {\r\n                    case 'both':\r\n                    case 'xy':\r\n                        ystrs.unshift(xstr);\r\n                        ystrs.unshift(opts.formatString);\r\n                        str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);\r\n                        break;\r\n                    case 'yx':\r\n                        ystrs.push(xstr);\r\n                        ystrs.unshift(opts.formatString);\r\n                        str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);\r\n                        break;\r\n                    case 'x':\r\n                        str = $.jqplot.sprintf.apply($.jqplot.sprintf, [opts.formatString, xstr]);\r\n                        break;\r\n                    case 'y':\r\n                        ystrs.unshift(opts.formatString);\r\n                        str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);\r\n                        break;\r\n                    default: // same as xy\r\n                        ystrs.unshift(xstr);\r\n                        ystrs.unshift(opts.formatString);\r\n                        str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs);\r\n                        break;\r\n                } \r\n            }\r\n            else {\r\n                switch (opts.tooltipAxes) {\r\n                    case 'both':\r\n                    case 'xy':\r\n                        str = xstr;\r\n                        for (var i=0; i<ystrs.length; i++) {\r\n                            str += opts.tooltipSeparator + ystrs[i];\r\n                        }\r\n                        break;\r\n                    case 'yx':\r\n                        str = '';\r\n                        for (var i=0; i<ystrs.length; i++) {\r\n                            str += ystrs[i] + opts.tooltipSeparator;\r\n                        }\r\n                        str += xstr;\r\n                        break;\r\n                    case 'x':\r\n                        str = xstr;\r\n                        break;\r\n                    case 'y':\r\n                        str = ystrs.join(opts.tooltipSeparator);\r\n                        break;\r\n                    default: // same as 'xy'\r\n                        str = xstr;\r\n                        for (var i=0; i<ystrs.length; i++) {\r\n                            str += opts.tooltipSeparator + ystrs[i];\r\n                        }\r\n                        break;\r\n                    \r\n                }                \r\n            }\r\n        }\r\n        else {\r\n            var str;\r\n            if (typeof opts.formatString ===  'string') {\r\n                str = $.jqplot.sprintf.apply($.jqplot.sprintf, [opts.formatString].concat(neighbor.data));\r\n            }\r\n\r\n            else {\r\n                if (opts.tooltipAxes == 'both' || opts.tooltipAxes == 'xy') {\r\n                    str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[0]) + opts.tooltipSeparator + $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[1]);\r\n                }\r\n                else if (opts.tooltipAxes == 'yx') {\r\n                    str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[1]) + opts.tooltipSeparator + $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[0]);\r\n                }\r\n                else if (opts.tooltipAxes == 'x') {\r\n                    str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[0]);\r\n                }\r\n                else if (opts.tooltipAxes == 'y') {\r\n                    str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[1]);\r\n                } \r\n            }\r\n        }\r\n        if ($.isFunction(opts.tooltipContentEditor)) {\r\n            // args str, seriesIndex, pointIndex are essential so the hook can look up\r\n            // extra data for the point.\r\n            str = opts.tooltipContentEditor(str, neighbor.seriesIndex, neighbor.pointIndex, plot);\r\n        }\r\n        elem.html(str);\r\n        var gridpos = {x:neighbor.gridData[0], y:neighbor.gridData[1]};\r\n        var ms = 0;\r\n        var fact = 0.707;\r\n        if (series.markerRenderer.show == true) { \r\n            ms = (series.markerRenderer.size + opts.sizeAdjust)/2;\r\n        }\r\n\r\n        var loc = locations;\r\n        if (series.fillToZero && series.fill && neighbor.data[1] < 0) {\r\n          loc = oppositeLocations;\r\n        }\r\n\r\n        switch (loc[locationIndicies[opts.tooltipLocation]]) {\r\n            case 'nw':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - fact * ms;\r\n                var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - fact * ms;\r\n                break;\r\n            case 'n':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;\r\n                var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - ms;\r\n                break;\r\n            case 'ne':\r\n                var x = gridpos.x + plot._gridPadding.left + opts.tooltipOffset + fact * ms;\r\n                var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - fact * ms;\r\n                break;\r\n            case 'e':\r\n                var x = gridpos.x + plot._gridPadding.left + opts.tooltipOffset + ms;\r\n                var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;\r\n                break;\r\n            case 'se':\r\n                var x = gridpos.x + plot._gridPadding.left + opts.tooltipOffset + fact * ms;\r\n                var y = gridpos.y + plot._gridPadding.top + opts.tooltipOffset + fact * ms;\r\n                break;\r\n            case 's':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2;\r\n                var y = gridpos.y + plot._gridPadding.top + opts.tooltipOffset + ms;\r\n                break;\r\n            case 'sw':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - fact * ms;\r\n                var y = gridpos.y + plot._gridPadding.top + opts.tooltipOffset + fact * ms;\r\n                break;\r\n            case 'w':\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - ms;\r\n                var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2;\r\n                break;\r\n            default: // same as 'nw'\r\n                var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - fact * ms;\r\n                var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - fact * ms;\r\n                break;\r\n        }\r\n        elem.css('left', x);\r\n        elem.css('top', y);\r\n        if (opts.fadeTooltip) {\r\n            // Fix for stacked up animations.  Thnanks Trevor!\r\n            elem.stop(true,true).fadeIn(opts.tooltipFadeSpeed);\r\n        }\r\n        else {\r\n            elem.show();\r\n        }\r\n        elem = null;\r\n        \r\n    }\r\n    \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        var hl = plot.plugins.highlighter;\r\n        var c = plot.plugins.cursor;\r\n        if (hl.show) {\r\n            if (neighbor == null && hl.isHighlighting) {\r\n                var evt = jQuery.Event('jqplotHighlighterUnhighlight');\r\n                plot.target.trigger(evt);\r\n\r\n                var ctx = hl.highlightCanvas._ctx;\r\n                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n                if (hl.fadeTooltip) {\r\n                    hl._tooltipElem.fadeOut(hl.tooltipFadeSpeed);\r\n                }\r\n                else {\r\n                    hl._tooltipElem.hide();\r\n                }\r\n                if (hl.bringSeriesToFront) {\r\n                    plot.restorePreviousSeriesOrder();\r\n                }\r\n                hl.isHighlighting = false;\r\n                hl.currentNeighbor = null;\r\n                ctx = null;\r\n            }\r\n            else if (neighbor != null && plot.series[neighbor.seriesIndex].showHighlight && !hl.isHighlighting) {\r\n                var evt = jQuery.Event('jqplotHighlighterHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data, plot];\r\n                plot.target.trigger(evt, ins);\r\n\r\n                hl.isHighlighting = true;\r\n                hl.currentNeighbor = neighbor;\r\n                if (hl.showMarker) {\r\n                    draw(plot, neighbor);\r\n                }\r\n                if (plot.series[neighbor.seriesIndex].show && hl.showTooltip && (!c || !c._zoom.started)) {\r\n                    showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor);\r\n                }\r\n                if (hl.bringSeriesToFront) {\r\n                    plot.moveSeriesToFront(neighbor.seriesIndex);\r\n                }\r\n            }\r\n            // check to see if we're highlighting the wrong point.\r\n            else if (neighbor != null && hl.isHighlighting && hl.currentNeighbor != neighbor) {\r\n                // highlighting the wrong point.\r\n\r\n                // if new series allows highlighting, highlight new point.\r\n                if (plot.series[neighbor.seriesIndex].showHighlight) {\r\n                    var ctx = hl.highlightCanvas._ctx;\r\n                    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\r\n                    hl.isHighlighting = true;\r\n                    hl.currentNeighbor = neighbor;\r\n                    if (hl.showMarker) {\r\n                        draw(plot, neighbor);\r\n                    }\r\n                    if (plot.series[neighbor.seriesIndex].show && hl.showTooltip && (!c || !c._zoom.started)) {\r\n                        showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor);\r\n                    }\r\n                    if (hl.bringSeriesToFront) {\r\n                        plot.moveSeriesToFront(neighbor.seriesIndex);\r\n                    }                    \r\n                }                \r\n            }\r\n        }\r\n    }\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.json2.js",
    "content": "/*\r\n    2010-11-01 Chris Leonello\r\n    \r\n    Slightly modified version of the original json2.js to put JSON\r\n    functions under the $.jqplot namespace.\r\n    \r\n    licensing and orignal comments follow:\r\n    \r\n    http://www.JSON.org/json2.js\r\n    2010-08-25\r\n    \r\n    Public Domain.\r\n\r\n    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\r\n\r\n    See http://www.JSON.org/js.html\r\n\r\n\r\n    This code should be minified before deployment.\r\n    See http://javascript.crockford.com/jsmin.html\r\n\r\n    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO\r\n    NOT CONTROL.\r\n\r\n\r\n    This file creates a global JSON object containing two methods: stringify\r\n    and parse.\r\n\r\n        $.jqplot.JSON.stringify(value, replacer, space)\r\n            value       any JavaScript value, usually an object or array.\r\n\r\n            replacer    an optional parameter that determines how object\r\n                        values are stringified for objects. It can be a\r\n                        function or an array of strings.\r\n\r\n            space       an optional parameter that specifies the indentation\r\n                        of nested structures. If it is omitted, the text will\r\n                        be packed without extra whitespace. If it is a number,\r\n                        it will specify the number of spaces to indent at each\r\n                        level. If it is a string (such as '\\t' or '&nbsp;'),\r\n                        it contains the characters used to indent at each level.\r\n\r\n            This method produces a JSON text from a JavaScript value.\r\n\r\n            When an object value is found, if the object contains a toJSON\r\n            method, its toJSON method will be called and the result will be\r\n            stringified. A toJSON method does not serialize: it returns the\r\n            value represented by the name/value pair that should be serialized,\r\n            or undefined if nothing should be serialized. The toJSON method\r\n            will be passed the key associated with the value, and this will be\r\n            bound to the value\r\n\r\n            For example, this would serialize Dates as ISO strings.\r\n\r\n                Date.prototype.toJSON = function (key) {\r\n                    function f(n) {\r\n                        // Format integers to have at least two digits.\r\n                        return n < 10 ? '0' + n : n;\r\n                    }\r\n\r\n                    return this.getUTCFullYear()   + '-' +\r\n                         f(this.getUTCMonth() + 1) + '-' +\r\n                         f(this.getUTCDate())      + 'T' +\r\n                         f(this.getUTCHours())     + ':' +\r\n                         f(this.getUTCMinutes())   + ':' +\r\n                         f(this.getUTCSeconds())   + 'Z';\r\n                };\r\n\r\n            You can provide an optional replacer method. It will be passed the\r\n            key and value of each member, with this bound to the containing\r\n            object. The value that is returned from your method will be\r\n            serialized. If your method returns undefined, then the member will\r\n            be excluded from the serialization.\r\n\r\n            If the replacer parameter is an array of strings, then it will be\r\n            used to select the members to be serialized. It filters the results\r\n            such that only members with keys listed in the replacer array are\r\n            stringified.\r\n\r\n            Values that do not have JSON representations, such as undefined or\r\n            functions, will not be serialized. Such values in objects will be\r\n            dropped; in arrays they will be replaced with null. You can use\r\n            a replacer function to replace those with JSON values.\r\n            $.jqplot.JSON.stringify(undefined) returns undefined.\r\n\r\n            The optional space parameter produces a stringification of the\r\n            value that is filled with line breaks and indentation to make it\r\n            easier to read.\r\n\r\n            If the space parameter is a non-empty string, then that string will\r\n            be used for indentation. If the space parameter is a number, then\r\n            the indentation will be that many spaces.\r\n\r\n            Example:\r\n\r\n            text = $.jqplot.JSON.stringify(['e', {pluribus: 'unum'}]);\r\n            // text is '[\"e\",{\"pluribus\":\"unum\"}]'\r\n\r\n\r\n            text = $.jqplot.JSON.stringify(['e', {pluribus: 'unum'}], null, '\\t');\r\n            // text is '[\\n\\t\"e\",\\n\\t{\\n\\t\\t\"pluribus\": \"unum\"\\n\\t}\\n]'\r\n\r\n            text = $.jqplot.JSON.stringify([new Date()], function (key, value) {\r\n                return this[key] instanceof Date ?\r\n                    'Date(' + this[key] + ')' : value;\r\n            });\r\n            // text is '[\"Date(---current time---)\"]'\r\n\r\n\r\n        $.jqplot.JSON.parse(text, reviver)\r\n            This method parses a JSON text to produce an object or array.\r\n            It can throw a SyntaxError exception.\r\n\r\n            The optional reviver parameter is a function that can filter and\r\n            transform the results. It receives each of the keys and values,\r\n            and its return value is used instead of the original value.\r\n            If it returns what it received, then the structure is not modified.\r\n            If it returns undefined then the member is deleted.\r\n\r\n            Example:\r\n\r\n            // Parse the text. Values that look like ISO date strings will\r\n            // be converted to Date objects.\r\n\r\n            myData = $.jqplot.JSON.parse(text, function (key, value) {\r\n                var a;\r\n                if (typeof value === 'string') {\r\n                    a =\r\n/^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2}(?:\\.\\d*)?)Z$/.exec(value);\r\n                    if (a) {\r\n                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],\r\n                            +a[5], +a[6]));\r\n                    }\r\n                }\r\n                return value;\r\n            });\r\n\r\n            myData = $.jqplot.JSON.parse('[\"Date(09/09/2001)\"]', function (key, value) {\r\n                var d;\r\n                if (typeof value === 'string' &&\r\n                        value.slice(0, 5) === 'Date(' &&\r\n                        value.slice(-1) === ')') {\r\n                    d = new Date(value.slice(5, -1));\r\n                    if (d) {\r\n                        return d;\r\n                    }\r\n                }\r\n                return value;\r\n            });\r\n\r\n\r\n    This is a reference implementation. You are free to copy, modify, or\r\n    redistribute.\r\n*/\r\n\r\n(function($) {\r\n\r\n    $.jqplot.JSON = window.JSON;\r\n\r\n    if (!window.JSON) {\r\n        $.jqplot.JSON = {};\r\n    }\r\n    \r\n    function f(n) {\r\n        // Format integers to have at least two digits.\r\n        return n < 10 ? '0' + n : n;\r\n    }\r\n\r\n    if (typeof Date.prototype.toJSON !== 'function') {\r\n\r\n        Date.prototype.toJSON = function (key) {\r\n\r\n            return isFinite(this.valueOf()) ?\r\n                   this.getUTCFullYear()   + '-' +\r\n                 f(this.getUTCMonth() + 1) + '-' +\r\n                 f(this.getUTCDate())      + 'T' +\r\n                 f(this.getUTCHours())     + ':' +\r\n                 f(this.getUTCMinutes())   + ':' +\r\n                 f(this.getUTCSeconds())   + 'Z' : null;\r\n        };\r\n\r\n        String.prototype.toJSON =\r\n        Number.prototype.toJSON =\r\n        Boolean.prototype.toJSON = function (key) {\r\n            return this.valueOf();\r\n        };\r\n    }\r\n\r\n    var cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\r\n        escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\r\n        gap,\r\n        indent,\r\n        meta = {    // table of character substitutions\r\n            '\\b': '\\\\b',\r\n            '\\t': '\\\\t',\r\n            '\\n': '\\\\n',\r\n            '\\f': '\\\\f',\r\n            '\\r': '\\\\r',\r\n            '\"' : '\\\\\"',\r\n            '\\\\': '\\\\\\\\'\r\n        },\r\n        rep;\r\n\r\n\r\n    function quote(string) {\r\n\r\n// If the string contains no control characters, no quote characters, and no\r\n// backslash characters, then we can safely slap some quotes around it.\r\n// Otherwise we must also replace the offending characters with safe escape\r\n// sequences.\r\n\r\n        escapable.lastIndex = 0;\r\n        return escapable.test(string) ?\r\n            '\"' + string.replace(escapable, function (a) {\r\n                var c = meta[a];\r\n                return typeof c === 'string' ? c :\r\n                    '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\r\n            }) + '\"' :\r\n            '\"' + string + '\"';\r\n    }\r\n\r\n\r\n    function str(key, holder) {\r\n\r\n// Produce a string from holder[key].\r\n\r\n        var i,          // The loop counter.\r\n            k,          // The member key.\r\n            v,          // The member value.\r\n            length,\r\n            mind = gap,\r\n            partial,\r\n            value = holder[key];\r\n\r\n// If the value has a toJSON method, call it to obtain a replacement value.\r\n\r\n        if (value && typeof value === 'object' &&\r\n                typeof value.toJSON === 'function') {\r\n            value = value.toJSON(key);\r\n        }\r\n\r\n// If we were called with a replacer function, then call the replacer to\r\n// obtain a replacement value.\r\n\r\n        if (typeof rep === 'function') {\r\n            value = rep.call(holder, key, value);\r\n        }\r\n\r\n// What happens next depends on the value's type.\r\n\r\n        switch (typeof value) {\r\n        case 'string':\r\n            return quote(value);\r\n\r\n        case 'number':\r\n\r\n// JSON numbers must be finite. Encode non-finite numbers as null.\r\n\r\n            return isFinite(value) ? String(value) : 'null';\r\n\r\n        case 'boolean':\r\n        case 'null':\r\n\r\n// If the value is a boolean or null, convert it to a string. Note:\r\n// typeof null does not produce 'null'. The case is included here in\r\n// the remote chance that this gets fixed someday.\r\n\r\n            return String(value);\r\n\r\n// If the type is 'object', we might be dealing with an object or an array or\r\n// null.\r\n\r\n        case 'object':\r\n\r\n// Due to a specification blunder in ECMAScript, typeof null is 'object',\r\n// so watch out for that case.\r\n\r\n            if (!value) {\r\n                return 'null';\r\n            }\r\n\r\n// Make an array to hold the partial results of stringifying this object value.\r\n\r\n            gap += indent;\r\n            partial = [];\r\n\r\n// Is the value an array?\r\n\r\n            if (Object.prototype.toString.apply(value) === '[object Array]') {\r\n\r\n// The value is an array. Stringify every element. Use null as a placeholder\r\n// for non-JSON values.\r\n\r\n                length = value.length;\r\n                for (i = 0; i < length; i += 1) {\r\n                    partial[i] = str(i, value) || 'null';\r\n                }\r\n\r\n// Join all of the elements together, separated with commas, and wrap them in\r\n// brackets.\r\n\r\n                v = partial.length === 0 ? '[]' :\r\n                    gap ? '[\\n' + gap +\r\n                            partial.join(',\\n' + gap) + '\\n' +\r\n                                mind + ']' :\r\n                          '[' + partial.join(',') + ']';\r\n                gap = mind;\r\n                return v;\r\n            }\r\n\r\n// If the replacer is an array, use it to select the members to be stringified.\r\n\r\n            if (rep && typeof rep === 'object') {\r\n                length = rep.length;\r\n                for (i = 0; i < length; i += 1) {\r\n                    k = rep[i];\r\n                    if (typeof k === 'string') {\r\n                        v = str(k, value);\r\n                        if (v) {\r\n                            partial.push(quote(k) + (gap ? ': ' : ':') + v);\r\n                        }\r\n                    }\r\n                }\r\n            } else {\r\n\r\n// Otherwise, iterate through all of the keys in the object.\r\n\r\n                for (k in value) {\r\n                    if (Object.hasOwnProperty.call(value, k)) {\r\n                        v = str(k, value);\r\n                        if (v) {\r\n                            partial.push(quote(k) + (gap ? ': ' : ':') + v);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n// Join all of the member texts together, separated with commas,\r\n// and wrap them in braces.\r\n\r\n            v = partial.length === 0 ? '{}' :\r\n                gap ? '{\\n' + gap + partial.join(',\\n' + gap) + '\\n' +\r\n                        mind + '}' : '{' + partial.join(',') + '}';\r\n            gap = mind;\r\n            return v;\r\n        }\r\n    }\r\n\r\n// If the JSON object does not yet have a stringify method, give it one.\r\n\r\n    if (typeof $.jqplot.JSON.stringify !== 'function') {\r\n        $.jqplot.JSON.stringify = function (value, replacer, space) {\r\n\r\n// The stringify method takes a value and an optional replacer, and an optional\r\n// space parameter, and returns a JSON text. The replacer can be a function\r\n// that can replace values, or an array of strings that will select the keys.\r\n// A default replacer method can be provided. Use of the space parameter can\r\n// produce text that is more easily readable.\r\n\r\n            var i;\r\n            gap = '';\r\n            indent = '';\r\n\r\n// If the space parameter is a number, make an indent string containing that\r\n// many spaces.\r\n\r\n            if (typeof space === 'number') {\r\n                for (i = 0; i < space; i += 1) {\r\n                    indent += ' ';\r\n                }\r\n\r\n// If the space parameter is a string, it will be used as the indent string.\r\n\r\n            } else if (typeof space === 'string') {\r\n                indent = space;\r\n            }\r\n\r\n// If there is a replacer, it must be a function or an array.\r\n// Otherwise, throw an error.\r\n\r\n            rep = replacer;\r\n            if (replacer && typeof replacer !== 'function' &&\r\n                    (typeof replacer !== 'object' ||\r\n                     typeof replacer.length !== 'number')) {\r\n                throw new Error('$.jqplot.JSON.stringify');\r\n            }\r\n\r\n// Make a fake root object containing our value under the key of ''.\r\n// Return the result of stringifying the value.\r\n\r\n            return str('', {'': value});\r\n        };\r\n    }\r\n\r\n\r\n// If the JSON object does not yet have a parse method, give it one.\r\n\r\n    if (typeof $.jqplot.JSON.parse !== 'function') {\r\n        $.jqplot.JSON.parse = function (text, reviver) {\r\n\r\n// The parse method takes a text and an optional reviver function, and returns\r\n// a JavaScript value if the text is a valid JSON text.\r\n\r\n            var j;\r\n\r\n            function walk(holder, key) {\r\n\r\n// The walk method is used to recursively walk the resulting structure so\r\n// that modifications can be made.\r\n\r\n                var k, v, value = holder[key];\r\n                if (value && typeof value === 'object') {\r\n                    for (k in value) {\r\n                        if (Object.hasOwnProperty.call(value, k)) {\r\n                            v = walk(value, k);\r\n                            if (v !== undefined) {\r\n                                value[k] = v;\r\n                            } else {\r\n                                delete value[k];\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                return reviver.call(holder, key, value);\r\n            }\r\n\r\n\r\n// Parsing happens in four stages. In the first stage, we replace certain\r\n// Unicode characters with escape sequences. JavaScript handles many characters\r\n// incorrectly, either silently deleting them, or treating them as line endings.\r\n\r\n            text = String(text);\r\n            cx.lastIndex = 0;\r\n            if (cx.test(text)) {\r\n                text = text.replace(cx, function (a) {\r\n                    return '\\\\u' +\r\n                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\r\n                });\r\n            }\r\n\r\n// In the second stage, we run the text against regular expressions that look\r\n// for non-JSON patterns. We are especially concerned with '()' and 'new'\r\n// because they can cause invocation, and '=' because it can cause mutation.\r\n// But just to be safe, we want to reject all unexpected forms.\r\n\r\n// We split the second stage into 4 regexp operations in order to work around\r\n// crippling inefficiencies in IE's and Safari's regexp engines. First we\r\n// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we\r\n// replace all simple value tokens with ']' characters. Third, we delete all\r\n// open brackets that follow a colon or comma or that begin the text. Finally,\r\n// we look to see that the remaining characters are only whitespace or ']' or\r\n// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.\r\n\r\n            if (/^[\\],:{}\\s]*$/.test(text.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']').replace(/(?:^|:|,)(?:\\s*\\[)+/g, ''))) {\r\n\r\n// In the third stage we use the eval function to compile the text into a\r\n// JavaScript structure. The '{' operator is subject to a syntactic ambiguity\r\n// in JavaScript: it can begin a block or an object literal. We wrap the text\r\n// in parens to eliminate the ambiguity.\r\n\r\n                j = eval('(' + text + ')');\r\n\r\n// In the optional fourth stage, we recursively walk the new structure, passing\r\n// each name/value pair to a reviver function for possible transformation.\r\n\r\n                return typeof reviver === 'function' ?\r\n                    walk({'': j}, '') : j;\r\n            }\r\n\r\n// If the text is not JSON parseable, then a SyntaxError is thrown.\r\n\r\n            throw new SyntaxError('$.jqplot.JSON.parse');\r\n        };\r\n    }\r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.logAxisRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n    *  class: $.jqplot.LogAxisRenderer\r\n    *  A plugin for a jqPlot to render a logarithmic axis.\r\n    * \r\n    *  To use this renderer, include the plugin in your source\r\n    *  > <script type=\"text/javascript\" language=\"javascript\" src=\"plugins/jqplot.logAxisRenderer.js\"></script>\r\n    *  \r\n    *  and supply the appropriate options to your plot\r\n    *  \r\n    *  > {axes:{xaxis:{renderer:$.jqplot.LogAxisRenderer}}}\r\n    **/ \r\n    $.jqplot.LogAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n        // prop: axisDefaults\r\n        // Default properties which will be applied directly to the series.\r\n        //\r\n        // Group: Properties\r\n        //\r\n        // Properties\r\n        //\r\n        // base - the logarithmic base, commonly 2, 10 or Math.E\r\n        // tickDistribution - Deprecated.  \"power\" distribution of ticks\r\n        // always used.  Option has no effect.\r\n        this.axisDefaults = {\r\n            base : 10,\r\n            tickDistribution :'power'\r\n        };\r\n    };\r\n    \r\n    $.jqplot.LogAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.LogAxisRenderer.prototype.constructor = $.jqplot.LogAxisRenderer;\r\n    \r\n    $.jqplot.LogAxisRenderer.prototype.init = function(options) {\r\n        // prop: drawBaseline\r\n        // True to draw the axis baseline.\r\n        this.drawBaseline = true;\r\n        // prop: minorTicks\r\n        // Number of ticks to add between \"major\" ticks.\r\n        // Major ticks are ticks supplied by user or auto computed.\r\n        // Minor ticks cannot be created by user.\r\n        this.minorTicks = 'auto';\r\n        this._scalefact = 1.0;\r\n\r\n        $.extend(true, this, options);\r\n\r\n        this._autoFormatString = '%d';\r\n        this._overrideFormatString = false;\r\n\r\n        for (var d in this.renderer.axisDefaults) {\r\n            if (this[d] == null) {\r\n                this[d] = this.renderer.axisDefaults[d];\r\n            }\r\n        }\r\n\r\n        this.resetDataBounds();\r\n    };\r\n    \r\n    $.jqplot.LogAxisRenderer.prototype.createTicks = function(plot) {\r\n        // we're are operating on an axis here\r\n        var ticks = this._ticks;\r\n        var userTicks = this.ticks;\r\n        var name = this.name;\r\n        var db = this._dataBounds;\r\n        var dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height;\r\n        var interval;\r\n        var min, max;\r\n        var pos1, pos2;\r\n        var tt, i;\r\n\r\n        var threshold = 30;\r\n        // For some reason scalefactor is screwing up ticks.\r\n        this._scalefact =  (Math.max(dim, threshold+1) - threshold)/300;\r\n\r\n        // if we already have ticks, use them.\r\n        // ticks must be in order of increasing value.\r\n        if (userTicks.length) {\r\n            // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed\r\n            for (i=0; i<userTicks.length; i++){\r\n                var ut = userTicks[i];\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                if (ut.constructor == Array) {\r\n                    t.value = ut[0];\r\n                    t.label = ut[1];\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(ut[0], this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n\r\n                else if ($.isPlainObject(ut)) {\r\n                    $.extend(true, t, ut);\r\n                    t.axis = this.name;\r\n                    this._ticks.push(t);\r\n                }\r\n                \r\n                else {\r\n                    t.value = ut;\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(ut, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n            this.numberTicks = userTicks.length;\r\n            this.min = this._ticks[0].value;\r\n            this.max = this._ticks[this.numberTicks-1].value;\r\n        }\r\n        \r\n        // we don't have any ticks yet, let's make some!\r\n        else if (this.min == null && this.max == null) {\r\n            min = db.min * (2 - this.padMin);\r\n            max = db.max * this.padMax;\r\n            \r\n            // if min and max are same, space them out a bit\r\n            if (min == max) {\r\n                var adj = 0.05;\r\n                min = min*(1-adj);\r\n                max = max*(1+adj);\r\n            }\r\n            \r\n            // perform some checks\r\n            if (this.min != null && this.min <= 0) {\r\n                throw new Error(\"Log axis minimum must be greater than 0\");\r\n            }\r\n            if (this.max != null && this.max <= 0) {\r\n                throw new Error(\"Log axis maximum must be greater than 0\");\r\n            }\r\n\r\n            function findCeil (val) {\r\n                var order = Math.pow(10, Math.floor(Math.log(val)/Math.LN10));\r\n                return Math.ceil(val/order) * order;\r\n            }\r\n\r\n            function findFloor(val) {\r\n                var order = Math.pow(10, Math.floor(Math.log(val)/Math.LN10));\r\n                return Math.floor(val/order) * order;\r\n            }\r\n\r\n            // var range = max - min;\r\n            var rmin, rmax;\r\n\r\n            // for power distribution, open up range to get a nice power of axis.renderer.base.\r\n            // power distribution won't respect the user's min/max settings.\r\n            rmin = Math.pow(this.base, Math.floor(Math.log(min)/Math.log(this.base)));\r\n            rmax = Math.pow(this.base, Math.ceil(Math.log(max)/Math.log(this.base)));\r\n\r\n            // // if min and max are same, space them out a bit\r\n            // if (rmin === rmax) {\r\n            //     var adj = 0.05;\r\n            //     rmin = rmin*(1-adj);\r\n            //     rmax = rmax*(1+adj);\r\n            // }\r\n\r\n            // Handle case where a data value was zero\r\n            if (rmin === 0) {\r\n              rmin = 1;\r\n            }\r\n\r\n            var order = Math.round(Math.log(rmin)/Math.LN10);\r\n\r\n            if (this.tickOptions == null || !this.tickOptions.formatString) {\r\n                this._overrideFormatString = true;\r\n            }\r\n\r\n            this.min = rmin;\r\n            this.max = rmax;\r\n            var range = this.max - this.min;            \r\n\r\n            var minorTicks = (this.minorTicks === 'auto') ? 0 : this.minorTicks;\r\n            var numberTicks;\r\n            if (this.numberTicks == null){\r\n                if (dim > 140) {\r\n                    numberTicks = Math.round(Math.log(this.max/this.min)/Math.log(this.base) + 1);\r\n                    if (numberTicks < 2) {\r\n                        numberTicks = 2;\r\n                    }\r\n                    if (minorTicks === 0) {\r\n                        var temp = dim/(numberTicks - 1);\r\n                        if (temp < 100) {\r\n                            minorTicks = 0;\r\n                        }\r\n                        else if (temp < 190) {\r\n                            minorTicks = 1;\r\n                        }\r\n                        else if (temp < 250) {\r\n                            minorTicks = 3;\r\n                        }\r\n                        else if (temp < 600) {\r\n                            minorTicks = 4;\r\n                        }\r\n                        else {\r\n                            minorTicks = 9;\r\n                        }\r\n                    }\r\n                }\r\n                else {\r\n                    numberTicks = 2;\r\n                    if (minorTicks === 0) {\r\n                        minorTicks = 1;\r\n                    }\r\n                    minorTicks = 0;\r\n                }\r\n            }\r\n            else {\r\n                numberTicks = this.numberTicks;\r\n            }\r\n\r\n            if (order >= 0 && minorTicks !== 3) {\r\n                this._autoFormatString = '%d';\r\n            }\r\n            // Adjust format string for case with 3 ticks where we'll have like 1, 2.5, 5, 7.5, 10\r\n            else if (order <= 0 && minorTicks === 3) {\r\n                var temp = -(order - 1);\r\n                this._autoFormatString = '%.'+ Math.abs(order-1) + 'f';\r\n            }\r\n\r\n            // Adjust format string for values less than 1.\r\n            else if (order < 0) {\r\n                var temp = -order;\r\n                this._autoFormatString = '%.'+ Math.abs(order) + 'f';\r\n            }\r\n\r\n            else {\r\n                this._autoFormatString = '%d';\r\n            }\r\n\r\n            var to, t, val, tt1, spread, interval;\r\n            for (var i=0; i<numberTicks; i++){\r\n                tt = Math.pow(this.base, i - numberTicks + 1) * this.max;\r\n\r\n                t = new this.tickRenderer(this.tickOptions);\r\n            \r\n                if (this._overrideFormatString) {\r\n                    t.formatString = this._autoFormatString;\r\n                }\r\n                \r\n                if (!this.showTicks) {\r\n                    t.showLabel = false;\r\n                    t.showMark = false;\r\n                }\r\n                else if (!this.showTickMarks) {\r\n                    t.showMark = false;\r\n                }\r\n                t.setTick(tt, this.name);\r\n                this._ticks.push(t);\r\n\r\n                if (minorTicks && i<numberTicks-1) {\r\n                    tt1 = Math.pow(this.base, i - numberTicks + 2) * this.max;\r\n                    spread = tt1 - tt;\r\n                    interval = tt1 / (minorTicks+1);\r\n                    for (var j=minorTicks-1; j>=0; j--) {\r\n                        val = tt1-interval*(j+1);\r\n                        t = new this.tickRenderer(this.tickOptions);\r\n            \r\n                        if (this._overrideFormatString && this._autoFormatString != '') {\r\n                            t.formatString = this._autoFormatString;\r\n                        }\r\n                        if (!this.showTicks) {\r\n                            t.showLabel = false;\r\n                            t.showMark = false;\r\n                        }\r\n                        else if (!this.showTickMarks) {\r\n                            t.showMark = false;\r\n                        }\r\n                        t.setTick(val, this.name);\r\n                        this._ticks.push(t);\r\n                    }\r\n                }       \r\n            }     \r\n        }\r\n\r\n        // min and max are set as would be the case with zooming\r\n        else if (this.min != null && this.max != null) {\r\n            var opts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null});\r\n            var nt, ti;\r\n            // don't have an interval yet, pick one that gives the most\r\n            // \"round\" ticks we can get.\r\n            if (this.numberTicks == null && this.tickInterval == null) {\r\n                // var threshold = 30;\r\n                var tdim = Math.max(dim, threshold+1);\r\n                var nttarget =  Math.ceil((tdim-threshold)/35 + 1);\r\n\r\n                var ret = $.jqplot.LinearTickGenerator.bestConstrainedInterval(this.min, this.max, nttarget);\r\n\r\n                this._autoFormatString = ret[3];\r\n                nt = ret[2];\r\n                ti = ret[4];\r\n\r\n                for (var i=0; i<nt; i++) {\r\n                    opts.value = this.min + i * ti;\r\n                    t = new this.tickRenderer(opts);\r\n                    \r\n                    if (this._overrideFormatString && this._autoFormatString != '') {\r\n                        t.formatString = this._autoFormatString;\r\n                    }\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n\r\n            // for loose zoom, number ticks and interval are also set.\r\n            else if (this.numberTicks != null && this.tickInterval != null) {\r\n                nt = this.numberTicks;\r\n                for (var i=0; i<nt; i++) {\r\n                    opts.value = this.min + i * this.tickInterval;\r\n                    t = new this.tickRenderer(opts);\r\n                    \r\n                    if (this._overrideFormatString && this._autoFormatString != '') {\r\n                        t.formatString = this._autoFormatString;\r\n                    }\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n        }\r\n    };\r\n    \r\n    $.jqplot.LogAxisRenderer.prototype.pack = function(pos, offsets) {\r\n        var lb = parseInt(this.base, 10);\r\n        var ticks = this._ticks;\r\n        var trans = function (v) { return Math.log(v)/Math.log(lb); };\r\n        var invtrans = function (v) { return Math.pow(Math.E, (Math.log(lb)*v)); };\r\n        var max = trans(this.max);\r\n        var min = trans(this.min);\r\n        var offmax = offsets.max;\r\n        var offmin = offsets.min;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        \r\n        for (var p in pos) {\r\n            this._elem.css(p, pos[p]);\r\n        }\r\n        \r\n        this._offsets = offsets;\r\n        // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left.\r\n        var pixellength = offmax - offmin;\r\n        var unitlength = max - min;\r\n        \r\n        // point to unit and unit to point conversions references to Plot DOM element top left corner.\r\n        this.p2u = function(p){\r\n            return invtrans((p - offmin) * unitlength / pixellength + min);\r\n        };\r\n        \r\n        this.u2p = function(u){\r\n            return (trans(u) - min) * pixellength / unitlength + offmin;\r\n        };\r\n        \r\n        if (this.name == 'xaxis' || this.name == 'x2axis'){\r\n            this.series_u2p = function(u){\r\n                return (trans(u) - min) * pixellength / unitlength;\r\n            };\r\n            this.series_p2u = function(p){\r\n                return invtrans(p * unitlength / pixellength + min);\r\n            };\r\n        }\r\n        // yaxis is max at top of canvas.\r\n        else {\r\n            this.series_u2p = function(u){\r\n                return (trans(u) - max) * pixellength / unitlength;\r\n            };\r\n            this.series_p2u = function(p){\r\n                return invtrans(p * unitlength / pixellength + max);\r\n            };\r\n        }\r\n        \r\n        if (this.show) {\r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {\r\n                        var shim;\r\n                        \r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                    if (t.angle < 0) {\r\n                                        shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    // position at start\r\n                                    else {\r\n                                        shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'end':\r\n                                    shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'start':\r\n                                    shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'middle':\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getWidth()/2;\r\n                        }\r\n                        // var shim = t.getWidth()/2;\r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('left', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                if (lshow) {\r\n                    var w = this._label._elem.outerWidth(true);\r\n                    this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px');\r\n                    if (this.name == 'xaxis') {\r\n                        this._label._elem.css('bottom', '0px');\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('top', '0px');\r\n                    }\r\n                    this._label.pack();\r\n                }\r\n            }\r\n            else {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {                        \r\n                        var shim;\r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                case 'end':\r\n                                    if (t.angle < 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'start':\r\n                                    if (t.angle > 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'middle':\r\n                                    // if (t.angle > 0) {\r\n                                    //     shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    // else {\r\n                                    //     shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getHeight()/2;\r\n                        }\r\n                        \r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('top', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                if (lshow) {\r\n                    var h = this._label._elem.outerHeight(true);\r\n                    this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px');\r\n                    if (this.name == 'yaxis') {\r\n                        this._label._elem.css('left', '0px');\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('right', '0px');\r\n                    }   \r\n                    this._label.pack();\r\n                }\r\n            }\r\n        }        \r\n    };\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.mekkoAxisRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    // class: $.jqplot.MekkoAxisRenderer\r\n    // An axis renderer for a Mekko chart.\r\n    // Should be used with a Mekko chart where the mekkoRenderer is used on the series.\r\n    // Displays the Y axis as a range from 0 to 1 (0 to 100%) and the x axis with a tick\r\n    // for each series scaled to the sum of all the y values.\r\n    $.jqplot.MekkoAxisRenderer = function() {\r\n    };\r\n    \r\n    // called with scope of axis object.\r\n    $.jqplot.MekkoAxisRenderer.prototype.init = function(options){\r\n        // prop: tickMode\r\n        // How to space the ticks on the axis.\r\n        // 'bar' will place a tick at the width of each bar.  \r\n        // This is the default for the x axis.\r\n        // 'even' will place ticks at even intervals.  This is\r\n        // the default for x2 axis and y axis.  y axis cannot be changed.\r\n        this.tickMode;\r\n        // prop: barLabelRenderer\r\n        // renderer to use to draw labels under each bar.\r\n        this.barLabelRenderer = $.jqplot.AxisLabelRenderer;\r\n        // prop: barLabels\r\n        // array of labels to put under each bar.\r\n        this.barLabels = this.barLabels || [];\r\n        // prop: barLabelOptions\r\n        // options object to pass to the bar label renderer.\r\n        this.barLabelOptions = {};\r\n        this.tickOptions = $.extend(true, {showGridline:false}, this.tickOptions);\r\n        this._barLabels = [];\r\n        $.extend(true, this, options);\r\n        if (this.name == 'yaxis') {\r\n            this.tickOptions.formatString = this.tickOptions.formatString || \"%d\\%\";\r\n        }\r\n        var db = this._dataBounds;\r\n        db.min = 0;\r\n        // for y axes, scale always go from 0 to 1 (0 to 100%)\r\n        if (this.name == 'yaxis' || this.name == 'y2axis') {\r\n            db.max = 100;\r\n            this.tickMode = 'even';\r\n        }\r\n        // For x axes, scale goes from 0 to sum of all y values.\r\n        else if (this.name == 'xaxis'){\r\n            this.tickMode = (this.tickMode == null) ? 'bar' : this.tickMode;\r\n            for (var i=0; i<this._series.length; i++) {\r\n                db.max += this._series[i]._sumy;\r\n            }\r\n        }\r\n        else if (this.name == 'x2axis'){\r\n            this.tickMode = (this.tickMode == null) ? 'even' : this.tickMode;\r\n            for (var i=0; i<this._series.length; i++) {\r\n                db.max += this._series[i]._sumy;\r\n            }\r\n        }\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.MekkoAxisRenderer.prototype.draw = function(ctx, plot) {\r\n        if (this.show) {\r\n            // populate the axis label and value properties.\r\n            // createTicks is a method on the renderer, but\r\n            // call it within the scope of the axis.\r\n            this.renderer.createTicks.call(this);\r\n            // fill a div with axes labels in the right direction.\r\n            // Need to pregenerate each axis to get its bounds and\r\n            // position it and the labels correctly on the plot.\r\n            var dim=0;\r\n            var temp;\r\n            \r\n            var elem = document.createElement('div');\r\n            this._elem = $(elem);\r\n            this._elem.addClass('jqplot-axis jqplot-'+this.name);\r\n            this._elem.css('position', 'absolute');\r\n            elem = null;\r\n            \r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                this._elem.width(this._plotDimensions.width);\r\n            }\r\n            else {\r\n                this._elem.height(this._plotDimensions.height);\r\n            }\r\n            \r\n            // draw the axis label\r\n            // create a _label object.\r\n            this.labelOptions.axis = this.name;\r\n            this._label = new this.labelRenderer(this.labelOptions);\r\n            if (this._label.show) {\r\n                this._elem.append(this._label.draw(ctx));\r\n            }\r\n            \r\n            var t, tick, elem;\r\n            if (this.showTicks) {\r\n                t = this._ticks;\r\n                for (var i=0; i<t.length; i++) {\r\n                    tick = t[i];\r\n                    if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) {\r\n                        this._elem.append(tick.draw(ctx));\r\n                    }\r\n                }\r\n            }\r\n            \r\n            // draw the series labels\r\n            for (i=0; i<this.barLabels.length; i++) {\r\n                this.barLabelOptions.axis = this.name;\r\n                this.barLabelOptions.label = this.barLabels[i];\r\n                this._barLabels.push(new this.barLabelRenderer(this.barLabelOptions));\r\n                if (this.tickMode != 'bar') {\r\n                    this._barLabels[i].show = false;\r\n                }\r\n                if (this._barLabels[i].show) {\r\n                    var elem = this._barLabels[i].draw(ctx, plot);\r\n                    elem.removeClass('jqplot-'+this.name+'-label');\r\n                    elem.addClass('jqplot-'+this.name+'-tick');\r\n                    elem.addClass('jqplot-mekko-barLabel');\r\n                    elem.appendTo(this._elem);\r\n                    elem = null;\r\n                }   \r\n            }\r\n            \r\n        }\r\n        return this._elem;\r\n    };\r\n    \r\n    // called with scope of an axis\r\n    $.jqplot.MekkoAxisRenderer.prototype.reset = function() {\r\n        this.min = this._min;\r\n        this.max = this._max;\r\n        this.tickInterval = this._tickInterval;\r\n        this.numberTicks = this._numberTicks;\r\n        // this._ticks = this.__ticks;\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.MekkoAxisRenderer.prototype.set = function() { \r\n        var dim = 0;\r\n        var temp;\r\n        var w = 0;\r\n        var h = 0;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        if (this.show && this.showTicks) {\r\n            var t = this._ticks;\r\n            for (var i=0; i<t.length; i++) {\r\n                var tick = t[i];\r\n                if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) {\r\n                    if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                        temp = tick._elem.outerHeight(true);\r\n                    }\r\n                    else {\r\n                        temp = tick._elem.outerWidth(true);\r\n                    }\r\n                    if (temp > dim) {\r\n                        dim = temp;\r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (lshow) {\r\n                w = this._label._elem.outerWidth(true);\r\n                h = this._label._elem.outerHeight(true); \r\n            }\r\n            if (this.name == 'xaxis') {\r\n                dim = dim + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'});\r\n            }\r\n            else if (this.name == 'x2axis') {\r\n                dim = dim + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', top:'0px'});\r\n            }\r\n            else if (this.name == 'yaxis') {\r\n                dim = dim + w;\r\n                this._elem.css({'width':dim+'px', left:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n            else {\r\n                dim = dim + w;\r\n                this._elem.css({'width':dim+'px', right:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n        }  \r\n    };    \r\n    \r\n    // called with scope of axis\r\n    $.jqplot.MekkoAxisRenderer.prototype.createTicks = function() {\r\n        // we're are operating on an axis here\r\n        var ticks = this._ticks;\r\n        var userTicks = this.ticks;\r\n        var name = this.name;\r\n        // databounds were set on axis initialization.\r\n        var db = this._dataBounds;\r\n        var dim, interval;\r\n        var min, max;\r\n        var pos1, pos2;\r\n        var t, tt, i, j;\r\n        \r\n        // if we already have ticks, use them.\r\n        // ticks must be in order of increasing value.\r\n        \r\n        if (userTicks.length) {\r\n            // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed\r\n            for (i=0; i<userTicks.length; i++){\r\n                var ut = userTicks[i];\r\n                var t = new this.tickRenderer(this.tickOptions);\r\n                if (ut.constructor == Array) {\r\n                    t.value = ut[0];\r\n                    t.label = ut[1];\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(ut[0], this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n                \r\n                else {\r\n                    t.value = ut;\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(ut, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n            this.numberTicks = userTicks.length;\r\n            this.min = this._ticks[0].value;\r\n            this.max = this._ticks[this.numberTicks-1].value;\r\n            this.tickInterval = (this.max - this.min) / (this.numberTicks - 1);\r\n        }\r\n        \r\n        // we don't have any ticks yet, let's make some!\r\n        else {\r\n            if (name == 'xaxis' || name == 'x2axis') {\r\n                dim = this._plotDimensions.width;\r\n            }\r\n            else {\r\n                dim = this._plotDimensions.height;\r\n            }\r\n            \r\n            // if min, max and number of ticks specified, user can't specify interval.\r\n            if (this.min != null && this.max != null && this.numberTicks != null) {\r\n                this.tickInterval = null;\r\n            }\r\n        \r\n            min = (this.min != null) ? this.min : db.min;\r\n            max = (this.max != null) ? this.max : db.max;\r\n            \r\n            // if min and max are same, space them out a bit.+\r\n            if (min == max) {\r\n                var adj = 0.05;\r\n                if (min > 0) {\r\n                    adj = Math.max(Math.log(min)/Math.LN10, 0.05);\r\n                }\r\n                min -= adj;\r\n                max += adj;\r\n            }\r\n\r\n            var range = max - min;\r\n            var rmin, rmax;\r\n            var temp, prev, curr;\r\n            var ynumticks = [3,5,6,11,21];\r\n            \r\n            // yaxis divide ticks in nice intervals from 0 to 1.\r\n            if (this.name == 'yaxis' || this.name == 'y2axis') { \r\n                this.min = 0;\r\n                this.max = 100; \r\n                // user didn't specify number of ticks.\r\n                if (!this.numberTicks){\r\n                    if (this.tickInterval) {\r\n                        this.numberTicks = 3 + Math.ceil(range / this.tickInterval);\r\n                    }\r\n                    else {\r\n                        temp = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing);\r\n                        for (i=0; i<ynumticks.length; i++) {\r\n                            curr = temp/ynumticks[i];\r\n                            if (curr == 1) {\r\n                                this.numberTicks = ynumticks[i];\r\n                                break;\r\n                            }\r\n                            else if (curr > 1) {\r\n                                prev = curr;\r\n                                continue;\r\n                            }\r\n                            else if (curr < 1) {\r\n                                // was prev or is curr closer to one?\r\n                                if (Math.abs(prev - 1) < Math.abs(curr - 1)) {\r\n                                    this.numberTicks = ynumticks[i-1];\r\n                                    break;\r\n                                }\r\n                                else {\r\n                                    this.numberTicks = ynumticks[i];\r\n                                    break;\r\n                                }\r\n                            }\r\n                            else if (i == ynumticks.length -1) {\r\n                                this.numberTicks = ynumticks[i];\r\n                            }\r\n                        }\r\n                        this.tickInterval = range / (this.numberTicks - 1);\r\n                    }\r\n                }\r\n                \r\n                // user did specify number of ticks.\r\n                else {\r\n                    this.tickInterval = range / (this.numberTicks - 1);\r\n                }\r\n\r\n                for (var i=0; i<this.numberTicks; i++){\r\n                    tt = this.min + i * this.tickInterval;\r\n                    t = new this.tickRenderer(this.tickOptions);\r\n                    // var t = new $.jqplot.AxisTickRenderer(this.tickOptions);\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(tt, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n            \r\n            // for x axes, have number ot ticks equal to number of series and ticks placed\r\n            // at sum of y values for each series.\r\n            else if (this.tickMode == 'bar') {\r\n                this.min = 0;\r\n                this.numberTicks = this._series.length + 1;\r\n                t = new this.tickRenderer(this.tickOptions);\r\n                if (!this.showTicks) {\r\n                    t.showLabel = false;\r\n                    t.showMark = false;\r\n                }\r\n                else if (!this.showTickMarks) {\r\n                    t.showMark = false;\r\n                }\r\n                t.setTick(0, this.name);\r\n                this._ticks.push(t);\r\n                \r\n                temp = 0;\r\n\r\n                for (i=1; i<this.numberTicks; i++){\r\n                    temp += this._series[i-1]._sumy;\r\n                    t = new this.tickRenderer(this.tickOptions);\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(temp, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n                this.max = this.max || temp;\r\n                \r\n                // if user specified a max and it is greater than sum, add a tick\r\n                if (this.max > temp) {\r\n                     t = new this.tickRenderer(this.tickOptions);\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(this.max, this.name);\r\n                    this._ticks.push(t);\r\n                    \r\n                }\r\n            }\r\n            \r\n            else if (this.tickMode == 'even') {\r\n                this.min = 0;\r\n                this.max = this.max || db.max;\r\n                // get a desired number of ticks\r\n                var nt = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing);\r\n                range = this.max - this.min;\r\n                this.numberTicks = nt;\r\n                this.tickInterval = range / (this.numberTicks - 1);\r\n\r\n                for (i=0; i<this.numberTicks; i++){\r\n                    tt = this.min + i * this.tickInterval;\r\n                    t = new this.tickRenderer(this.tickOptions);\r\n                    // var t = new $.jqplot.AxisTickRenderer(this.tickOptions);\r\n                    if (!this.showTicks) {\r\n                        t.showLabel = false;\r\n                        t.showMark = false;\r\n                    }\r\n                    else if (!this.showTickMarks) {\r\n                        t.showMark = false;\r\n                    }\r\n                    t.setTick(tt, this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n                \r\n            }\r\n        }\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.MekkoAxisRenderer.prototype.pack = function(pos, offsets) {\r\n        var ticks = this._ticks;\r\n        var max = this.max;\r\n        var min = this.min;\r\n        var offmax = offsets.max;\r\n        var offmin = offsets.min;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        \r\n        for (var p in pos) {\r\n            this._elem.css(p, pos[p]);\r\n        }\r\n        \r\n        this._offsets = offsets;\r\n        // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left.\r\n        var pixellength = offmax - offmin;\r\n        var unitlength = max - min;\r\n        \r\n        // point to unit and unit to point conversions references to Plot DOM element top left corner.\r\n        this.p2u = function(p){\r\n            return (p - offmin) * unitlength / pixellength + min;\r\n        };\r\n        \r\n        this.u2p = function(u){\r\n            return (u - min) * pixellength / unitlength + offmin;\r\n        };\r\n                \r\n        if (this.name == 'xaxis' || this.name == 'x2axis'){\r\n            this.series_u2p = function(u){\r\n                return (u - min) * pixellength / unitlength;\r\n            };\r\n            this.series_p2u = function(p){\r\n                return p * unitlength / pixellength + min;\r\n            };\r\n        }\r\n        \r\n        else {\r\n            this.series_u2p = function(u){\r\n                return (u - max) * pixellength / unitlength;\r\n            };\r\n            this.series_p2u = function(p){\r\n                return p * unitlength / pixellength + max;\r\n            };\r\n        }\r\n        \r\n        if (this.show) {\r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {\r\n                        var shim;\r\n                        \r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'xaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    // position at start\r\n                                    else {\r\n                                        shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'end':\r\n                                    shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'start':\r\n                                    shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'middle':\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getWidth()/2;\r\n                        }\r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('left', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                var w;\r\n                if (lshow) {\r\n                    w = this._label._elem.outerWidth(true);\r\n                    this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px');\r\n                    if (this.name == 'xaxis') {\r\n                        this._label._elem.css('bottom', '0px');\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('top', '0px');\r\n                    }\r\n                    this._label.pack();\r\n                }\r\n                // now show the labels under the bars.\r\n                var b, l, r;\r\n                for (var i=0; i<this.barLabels.length; i++) {\r\n                    b = this._barLabels[i];\r\n                    if (b.show) {\r\n                        w = b.getWidth();\r\n                        l = this._ticks[i].getLeft() + this._ticks[i].getWidth();\r\n                        r = this._ticks[i+1].getLeft();\r\n                        b._elem.css('left', (r+l-w)/2+'px');\r\n                        b._elem.css('top', this._ticks[i]._elem.css('top'));\r\n                        b.pack();\r\n                    }\r\n                }\r\n            }\r\n            else {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {                        \r\n                        var shim;\r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'yaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                case 'end':\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'start':\r\n                                    if (t.angle > 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'middle':\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getHeight()/2;\r\n                        }\r\n                        \r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('top', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                if (lshow) {\r\n                    var h = this._label._elem.outerHeight(true);\r\n                    this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px');\r\n                    if (this.name == 'yaxis') {\r\n                        this._label._elem.css('left', '0px');\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('right', '0px');\r\n                    }   \r\n                    this._label.pack();\r\n                }\r\n            }\r\n        }\r\n    };\r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.mekkoRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.MekkoRenderer\r\n     * Draws a Mekko style chart which shows 3 dimensional data on a 2 dimensional graph.\r\n     * the <$.jqplot.MekkoAxisRenderer> should be used with mekko charts.  The mekko renderer\r\n     * overrides the default legend renderer with its own $.jqplot.MekkoLegendRenderer\r\n     * which allows more flexibility to specify number of rows and columns in the legend.\r\n     * \r\n     * Data is specified per bar in the chart.  You can specify data as an array of y values, or as \r\n     * an array of [label, value] pairs.  Note that labels are used only on the first series.  \r\n     * Labels on subsequent series are ignored:\r\n     * \r\n     * > bar1 = [['shirts', 8],['hats', 14],['shoes', 6],['gloves', 16],['dolls', 12]];\r\n     * > bar2 = [15,6,9,13,6];\r\n     * > bar3 = [['grumpy',4],['sneezy',2],['happy',7],['sleepy',9],['doc',7]];\r\n     * \r\n     * If you want to place labels for each bar under the axis, you use the barLabels option on \r\n     * the axes.  The bar labels can be styled with the \".jqplot-mekko-barLabel\" css class.\r\n     * \r\n     * > barLabels = ['Mickey Mouse', 'Donald Duck', 'Goofy'];\r\n     * > axes:{xaxis:{barLabels:barLabels}}\r\n     * \r\n     */\r\n    \r\n    \r\n    $.jqplot.MekkoRenderer = function(){\r\n        this.shapeRenderer = new $.jqplot.ShapeRenderer();\r\n        // prop: borderColor\r\n        // color of the borders between areas on the chart\r\n        this.borderColor = null;\r\n        // prop: showBorders\r\n        // True to draw borders lines between areas on the chart.\r\n        // False will draw borders lines with the same color as the area.\r\n        this.showBorders = true;\r\n    };\r\n    \r\n    // called with scope of series.\r\n    $.jqplot.MekkoRenderer.prototype.init = function(options, plot) {\r\n        this.fill = false;\r\n        this.fillRect = true;\r\n        this.strokeRect = true;\r\n        this.shadow = false;\r\n        // width of bar on x axis.\r\n        this._xwidth = 0;\r\n        this._xstart = 0;\r\n        $.extend(true, this.renderer, options);\r\n        // set the shape renderer options\r\n        var opts = {lineJoin:'miter', lineCap:'butt', isarc:false, fillRect:this.fillRect, strokeRect:this.strokeRect};\r\n        this.renderer.shapeRenderer.init(opts);\r\n        plot.axes.x2axis._series.push(this);\r\n        this._type = 'mekko';\r\n    };\r\n    \r\n    // Method: setGridData\r\n    // converts the user data values to grid coordinates and stores them\r\n    // in the gridData array.  Will convert user data into appropriate\r\n    // rectangles.\r\n    // Called with scope of a series.\r\n    $.jqplot.MekkoRenderer.prototype.setGridData = function(plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var data = this._plotData;\r\n        this.gridData = [];\r\n        // figure out width on x axis.\r\n        // this._xwidth = this._sumy / plot._sumy * this.canvas.getWidth();\r\n        this._xwidth = xp(this._sumy) - xp(0);\r\n        if (this.index>0) {\r\n            this._xstart = plot.series[this.index-1]._xstart + plot.series[this.index-1]._xwidth;\r\n        }\r\n        var totheight = this.canvas.getHeight();\r\n        var sumy = 0;\r\n        var cury;\r\n        var curheight;\r\n        for (var i=0; i<data.length; i++) {\r\n            if (data[i] != null) {\r\n                sumy += data[i][1];\r\n                cury = totheight - (sumy / this._sumy * totheight);\r\n                curheight = data[i][1] / this._sumy * totheight;\r\n                this.gridData.push([this._xstart, cury, this._xwidth, curheight]);\r\n            }\r\n        }\r\n    };\r\n    \r\n    // Method: makeGridData\r\n    // converts any arbitrary data values to grid coordinates and\r\n    // returns them.  This method exists so that plugins can use a series'\r\n    // linerenderer to generate grid data points without overwriting the\r\n    // grid data associated with that series.\r\n    // Called with scope of a series.\r\n    $.jqplot.MekkoRenderer.prototype.makeGridData = function(data, plot) {\r\n        // recalculate the grid data\r\n        // figure out width on x axis.\r\n        var xp = this._xaxis.series_u2p;\r\n        var totheight = this.canvas.getHeight();\r\n        var sumy = 0;\r\n        var cury;\r\n        var curheight;\r\n        var gd = [];\r\n        for (var i=0; i<data.length; i++) {\r\n            if (data[i] != null) {\r\n                sumy += data[i][1];\r\n                cury = totheight - (sumy / this._sumy * totheight);\r\n                curheight = data[i][1] / this._sumy * totheight;\r\n                gd.push([this._xstart, cury, this._xwidth, curheight]);\r\n            }\r\n        }\r\n        return gd;\r\n    };\r\n    \r\n\r\n    // called within scope of series.\r\n    $.jqplot.MekkoRenderer.prototype.draw = function(ctx, gd, options) {\r\n        var i;\r\n        var opts = (options != undefined) ? options : {};\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);\r\n        ctx.save();\r\n        if (gd.length) {\r\n            if (showLine) {\r\n                for (i=0; i<gd.length; i++){\r\n                    opts.fillStyle = colorGenerator.next();\r\n                    if (this.renderer.showBorders) {\r\n                        opts.strokeStyle = this.renderer.borderColor;\r\n                    }\r\n                    else {\r\n                        opts.strokeStyle = opts.fillStyle;\r\n                    }\r\n                    this.renderer.shapeRenderer.draw(ctx, gd[i], opts);\r\n                }\r\n            }\r\n        }\r\n        \r\n        ctx.restore();\r\n    };  \r\n    \r\n    $.jqplot.MekkoRenderer.prototype.drawShadow = function(ctx, gd, options) {\r\n        // This is a no-op, no shadows on mekko charts.\r\n    };\r\n    \r\n    /**\r\n     * Class: $.jqplot.MekkoLegendRenderer\r\n     * Legend renderer used by mekko charts with options for \r\n     * controlling number or rows and columns as well as placement\r\n     * outside of plot area.\r\n     * \r\n     */\r\n    $.jqplot.MekkoLegendRenderer = function(){\r\n        //\r\n    };\r\n    \r\n    $.jqplot.MekkoLegendRenderer.prototype.init = function(options) {\r\n        // prop: numberRows\r\n        // Maximum number of rows in the legend.  0 or null for unlimited.\r\n        this.numberRows = null;\r\n        // prop: numberColumns\r\n        // Maximum number of columns in the legend.  0 or null for unlimited.\r\n        this.numberColumns = null;\r\n        // this will override the placement option on the Legend object\r\n        this.placement = \"outside\";\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    // called with scope of legend\r\n    $.jqplot.MekkoLegendRenderer.prototype.draw = function() {\r\n        var legend = this;\r\n        if (this.show) {\r\n            var series = this._series;\r\n            var ss = 'position:absolute;';\r\n            ss += (this.background) ? 'background:'+this.background+';' : '';\r\n            ss += (this.border) ? 'border:'+this.border+';' : '';\r\n            ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';\r\n            ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : '';\r\n            ss += (this.textColor) ? 'color:'+this.textColor+';' : '';\r\n            this._elem = $('<table class=\"jqplot-table-legend\" style=\"'+ss+'\"></table>');\r\n            // Mekko charts  legends don't go by number of series, but by number of data points\r\n            // in the series.  Refactor things here for that.\r\n            \r\n            var pad = false, \r\n                reverse = true,    // mekko charts are always stacked, so reverse\r\n                nr, nc;\r\n            var s = series[0];\r\n            var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);\r\n            \r\n            if (s.show) {\r\n                var pd = s.data;\r\n                if (this.numberRows) {\r\n                    nr = this.numberRows;\r\n                    if (!this.numberColumns){\r\n                        nc = Math.ceil(pd.length/nr);\r\n                    }\r\n                    else{\r\n                        nc = this.numberColumns;\r\n                    }\r\n                }\r\n                else if (this.numberColumns) {\r\n                    nc = this.numberColumns;\r\n                    nr = Math.ceil(pd.length/this.numberColumns);\r\n                }\r\n                else {\r\n                    nr = pd.length;\r\n                    nc = 1;\r\n                }\r\n                \r\n                var i, j, tr, td1, td2, lt, rs, color;\r\n                var idx = 0;    \r\n                \r\n                for (i=0; i<nr; i++) {\r\n                    if (reverse){\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').prependTo(this._elem);\r\n                    }\r\n                    else{\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').appendTo(this._elem);\r\n                    }\r\n                    for (j=0; j<nc; j++) {\r\n                        if (idx < pd.length) {\r\n                            lt = this.labels[idx] || pd[idx][0].toString();\r\n                            color = colorGenerator.next();\r\n                            if (!reverse){\r\n                                if (i>0){\r\n                                    pad = true;\r\n                                }\r\n                                else{\r\n                                    pad = false;\r\n                                }\r\n                            }\r\n                            else{\r\n                                if (i == nr -1){\r\n                                    pad = false;\r\n                                }\r\n                                else{\r\n                                    pad = true;\r\n                                }\r\n                            }\r\n                            rs = (pad) ? this.rowSpacing : '0';\r\n                \r\n                            td1 = $('<td class=\"jqplot-table-legend\" style=\"text-align:center;padding-top:'+rs+';\">'+\r\n                                '<div><div class=\"jqplot-table-legend-swatch\" style=\"border-color:'+color+';\"></div>'+\r\n                                '</div></td>');\r\n                            td2 = $('<td class=\"jqplot-table-legend\" style=\"padding-top:'+rs+';\"></td>');\r\n                            if (this.escapeHtml){\r\n                                td2.text(lt);\r\n                            }\r\n                            else {\r\n                                td2.html(lt);\r\n                            }\r\n                            if (reverse) {\r\n                                td2.prependTo(tr);\r\n                                td1.prependTo(tr);\r\n                            }\r\n                            else {\r\n                                td1.appendTo(tr);\r\n                                td2.appendTo(tr);\r\n                            }\r\n                            pad = true;\r\n                        }\r\n                        idx++;\r\n                    }   \r\n                }\r\n\r\n                tr = null;\r\n                td1 = null;\r\n                td2 = null;\r\n            }\r\n        }\r\n        return this._elem;\r\n    };\r\n    \r\n    $.jqplot.MekkoLegendRenderer.prototype.pack = function(offsets) {\r\n        if (this.show) {\r\n            // fake a grid for positioning\r\n            var grid = {_top:offsets.top, _left:offsets.left, _right:offsets.right, _bottom:this._plotDimensions.height - offsets.bottom};        \r\n            if (this.placement == 'insideGrid') {\r\n                switch (this.location) {\r\n                    case 'nw':\r\n                        var a = grid._left + this.xoffset;\r\n                        var b = grid._top + this.yoffset;\r\n                        this._elem.css('left', a);\r\n                        this._elem.css('top', b);\r\n                        break;\r\n                    case 'n':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = grid._top + this.yoffset;\r\n                        this._elem.css('left', a);\r\n                        this._elem.css('top', b);\r\n                        break;\r\n                    case 'ne':\r\n                        var a = offsets.right + this.xoffset;\r\n                        var b = grid._top + this.yoffset;\r\n                        this._elem.css({right:a, top:b});\r\n                        break;\r\n                    case 'e':\r\n                        var a = offsets.right + this.xoffset;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({right:a, top:b});\r\n                        break;\r\n                    case 'se':\r\n                        var a = offsets.right + this.xoffset;\r\n                        var b = offsets.bottom + this.yoffset;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                    case 's':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = offsets.bottom + this.yoffset;\r\n                        this._elem.css({left:a, bottom:b});\r\n                        break;\r\n                    case 'sw':\r\n                        var a = grid._left + this.xoffset;\r\n                        var b = offsets.bottom + this.yoffset;\r\n                        this._elem.css({left:a, bottom:b});\r\n                        break;\r\n                    case 'w':\r\n                        var a = grid._left + this.xoffset;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    default:  // same as 'se'\r\n                        var a = grid._right - this.xoffset;\r\n                        var b = grid._bottom + this.yoffset;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                }\r\n                \r\n            }\r\n            else {\r\n                switch (this.location) {\r\n                    case 'nw':\r\n                        var a = this._plotDimensions.width - grid._left + this.xoffset;\r\n                        var b = grid._top + this.yoffset;\r\n                        this._elem.css('right', a);\r\n                        this._elem.css('top', b);\r\n                        break;\r\n                    case 'n':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = this._plotDimensions.height - grid._top + this.yoffset;\r\n                        this._elem.css('left', a);\r\n                        this._elem.css('bottom', b);\r\n                        break;\r\n                    case 'ne':\r\n                        var a = this._plotDimensions.width - offsets.right + this.xoffset;\r\n                        var b = grid._top + this.yoffset;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    case 'e':\r\n                        var a = this._plotDimensions.width - offsets.right + this.xoffset;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    case 'se':\r\n                        var a = this._plotDimensions.width - offsets.right + this.xoffset;\r\n                        var b = offsets.bottom + this.yoffset;\r\n                        this._elem.css({left:a, bottom:b});\r\n                        break;\r\n                    case 's':\r\n                        var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2;\r\n                        var b = this._plotDimensions.height - offsets.bottom + this.yoffset;\r\n                        this._elem.css({left:a, top:b});\r\n                        break;\r\n                    case 'sw':\r\n                        var a = this._plotDimensions.width - grid._left + this.xoffset;\r\n                        var b = offsets.bottom + this.yoffset;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                    case 'w':\r\n                        var a = this._plotDimensions.width - grid._left + this.xoffset;\r\n                        var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2;\r\n                        this._elem.css({right:a, top:b});\r\n                        break;\r\n                    default:  // same as 'se'\r\n                        var a = grid._right - this.xoffset;\r\n                        var b = grid._bottom + this.yoffset;\r\n                        this._elem.css({right:a, bottom:b});\r\n                        break;\r\n                }\r\n            }\r\n        } \r\n    };\r\n    \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        options = options || {};\r\n        options.axesDefaults = options.axesDefaults || {};\r\n        options.legend = options.legend || {};\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer == $.jqplot.MekkoRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer == $.jqplot.MekkoRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.MekkoAxisRenderer;\r\n            options.legend.renderer = $.jqplot.MekkoLegendRenderer;\r\n            options.legend.preDraw = true;\r\n        }\r\n    }\r\n    \r\n    $.jqplot.preInitHooks.push(preInit);\r\n    \r\n})(jQuery);    \r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.meterGaugeRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.MeterGaugeRenderer\r\n     * Plugin renderer to draw a meter gauge chart.\r\n     * \r\n     * Data consists of a single series with 1 data point to position the gauge needle.\r\n     * \r\n     * To use this renderer, you need to include the \r\n     * meter gauge renderer plugin, for example:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.meterGaugeRenderer.js\"></script>\r\n     * \r\n     * Properties described here are passed into the $.jqplot function\r\n     * as options on the series renderer.  For example:\r\n     * \r\n     * > plot0 = $.jqplot('chart0',[[18]],{\r\n     * >     title: 'Network Speed',\r\n     * >     seriesDefaults: {\r\n     * >         renderer: $.jqplot.MeterGaugeRenderer,\r\n     * >         rendererOptions: {\r\n     * >             label: 'MB/s'\r\n     * >         }\r\n     * >     }\r\n     * > });\r\n     * \r\n     * A meterGauge plot does not support events.\r\n     */\r\n    $.jqplot.MeterGaugeRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.MeterGaugeRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.MeterGaugeRenderer.prototype.constructor = $.jqplot.MeterGaugeRenderer;\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.MeterGaugeRenderer.prototype.init = function(options) {\r\n        // Group: Properties\r\n        //\r\n        // prop: diameter\r\n        // Outer diameter of the meterGauge, auto computed by default\r\n        this.diameter = null;\r\n        // prop: padding\r\n        // padding between the meterGauge and plot edges, auto\r\n        // calculated by default.\r\n        this.padding = null;\r\n        // prop: shadowOffset\r\n        // offset of the shadow from the gauge ring and offset of \r\n        // each succesive stroke of the shadow from the last.\r\n        this.shadowOffset = 2;\r\n        // prop: shadowAlpha\r\n        // transparency of the shadow (0 = transparent, 1 = opaque)\r\n        this.shadowAlpha = 0.07;\r\n        // prop: shadowDepth\r\n        // number of strokes to apply to the shadow, \r\n        // each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 4;\r\n        // prop: background\r\n        // background color of the inside of the gauge.\r\n        this.background = \"#efefef\";\r\n        // prop: ringColor\r\n        // color of the outer ring, hub, and needle of the gauge.\r\n        this.ringColor = \"#BBC6D0\";\r\n        // needle color not implemented yet.\r\n        this.needleColor = \"#C3D3E5\";\r\n        // prop: tickColor\r\n        // color of the tick marks around the gauge.\r\n        this.tickColor = \"#989898\";\r\n        // prop: ringWidth\r\n        // width of the ring around the gauge.  Auto computed by default.\r\n        this.ringWidth = null;\r\n        // prop: min\r\n        // Minimum value on the gauge.  Auto computed by default\r\n        this.min;\r\n        // prop: max\r\n        // Maximum value on the gauge. Auto computed by default\r\n        this.max;\r\n        // prop: ticks\r\n        // Array of tick values. Auto computed by default.\r\n        this.ticks = [];\r\n        // prop: showTicks\r\n        // true to show ticks around gauge.\r\n        this.showTicks = true;\r\n        // prop: showTickLabels\r\n        // true to show tick labels next to ticks.\r\n        this.showTickLabels = true;\r\n        // prop: label\r\n        // A gauge label like 'kph' or 'Volts'\r\n        this.label = null;\r\n        // prop: labelHeightAdjust\r\n        // Number of Pixels to offset the label up (-) or down (+) from its default position.\r\n        this.labelHeightAdjust = 0;\r\n        // prop: labelPosition\r\n        // Where to position the label, either 'inside' or 'bottom'.\r\n        this.labelPosition = 'inside';\r\n        // prop: intervals\r\n        // Array of ranges to be drawn around the gauge.\r\n        // Array of form:\r\n        // > [value1, value2, ...]\r\n        // indicating the values for the first, second, ... intervals.\r\n        this.intervals = [];\r\n        // prop: intervalColors\r\n        // Array of colors to use for the intervals.\r\n        this.intervalColors = [ \"#4bb2c5\", \"#EAA228\", \"#c5b47f\", \"#579575\", \"#839557\", \"#958c12\", \"#953579\", \"#4b5de4\", \"#d8b83f\", \"#ff5800\", \"#0085cc\", \"#c747a3\", \"#cddf54\", \"#FBD178\", \"#26B4E3\", \"#bd70c7\"];\r\n        // prop: intervalInnerRadius\r\n        // Radius of the inner circle of the interval ring.\r\n        this.intervalInnerRadius =  null;\r\n        // prop: intervalOuterRadius\r\n        // Radius of the outer circle of the interval ring.\r\n        this.intervalOuterRadius = null;\r\n        this.tickRenderer = $.jqplot.MeterGaugeTickRenderer;\r\n        // ticks spaced every 1, 2, 2.5, 5, 10, 20, .1, .2, .25, .5, etc.\r\n        this.tickPositions = [1, 2, 2.5, 5, 10];\r\n        // prop: tickSpacing\r\n        // Degrees between ticks.  This is a target number, if \r\n        // incompatible span and ticks are supplied, a suitable\r\n        // spacing close to this value will be computed.\r\n        this.tickSpacing = 30;\r\n        this.numberMinorTicks = null;\r\n        // prop: hubRadius\r\n        // Radius of the hub at the bottom center of gauge which the needle attaches to.\r\n        // Auto computed by default\r\n        this.hubRadius = null;\r\n        // prop: tickPadding\r\n        // padding of the tick marks to the outer ring and the tick labels to marks.\r\n        // Auto computed by default.\r\n        this.tickPadding = null;\r\n        // prop: needleThickness\r\n        // Maximum thickness the needle.  Auto computed by default.\r\n        this.needleThickness = null;\r\n        // prop: needlePad\r\n        // Padding between needle and inner edge of the ring when the needle is at the min or max gauge value.\r\n        this.needlePad = 6;\r\n        // prop: pegNeedle\r\n        // True will stop needle just below/above the  min/max values if data is below/above min/max,\r\n        // as if the meter is \"pegged\".\r\n        this.pegNeedle = true;\r\n        this._type = 'meterGauge';\r\n        \r\n        $.extend(true, this, options);\r\n        this.type = null;\r\n        this.numberTicks = null;\r\n        this.tickInterval = null;\r\n        // span, the sweep (in degrees) from min to max.  This gauge is \r\n        // a semi-circle.\r\n        this.span = 180;\r\n        // get rid of this nonsense\r\n        // this.innerSpan = this.span;\r\n        if (this.type == 'circular') {\r\n            this.semiCircular = false;\r\n        }\r\n        else if (this.type != 'circular') {\r\n            this.semiCircular = true;\r\n        }\r\n        else {\r\n            this.semiCircular = (this.span <= 180) ? true : false;\r\n        }\r\n        this._tickPoints = [];\r\n        // reference to label element.\r\n        this._labelElem = null;\r\n        \r\n        // start the gauge at the beginning of the span\r\n        this.startAngle = (90 + (360 - this.span)/2) * Math.PI/180;\r\n        this.endAngle = (90 - (360 - this.span)/2) * Math.PI/180;\r\n        \r\n        this.setmin = !!(this.min == null);\r\n        this.setmax = !!(this.max == null);\r\n        \r\n        // if given intervals and is an array of values, create labels and colors.\r\n        if (this.intervals.length) {\r\n            if (this.intervals[0].length == null || this.intervals.length == 1) {\r\n                for (var i=0; i<this.intervals.length; i++) {\r\n                    this.intervals[i] = [this.intervals[i], this.intervals[i], this.intervalColors[i]];\r\n                }\r\n            }\r\n            else if (this.intervals[0].length == 2) {\r\n                for (i=0; i<this.intervals.length; i++) {\r\n                    this.intervals[i] = [this.intervals[i][0], this.intervals[i][1], this.intervalColors[i]];\r\n                }\r\n            }\r\n        }\r\n        \r\n        // compute min, max and ticks if not supplied:\r\n        if (this.ticks.length) {\r\n            if (this.ticks[0].length == null || this.ticks[0].length == 1) {\r\n                for (var i=0; i<this.ticks.length; i++) {\r\n                    this.ticks[i] = [this.ticks[i], this.ticks[i]];\r\n                }\r\n            }\r\n            this.min = (this.min == null) ? this.ticks[0][0] : this.min;\r\n            this.max = (this.max == null) ? this.ticks[this.ticks.length-1][0] : this.max;\r\n            this.setmin = false;\r\n            this.setmax = false;\r\n            this.numberTicks = this.ticks.length;\r\n            this.tickInterval = this.ticks[1][0] - this.ticks[0][0];\r\n            this.tickFactor = Math.floor(parseFloat((Math.log(this.tickInterval)/Math.log(10)).toFixed(11)));\r\n            // use the first interal to calculate minor ticks;\r\n            this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor);\r\n            if (!this.numberMinorTicks) {\r\n                this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1);\r\n            }\r\n            if (!this.numberMinorTicks) {\r\n                this.numberMinorTicks = 1;\r\n            }\r\n        }\r\n        \r\n        else if (this.intervals.length) {\r\n            this.min = (this.min == null) ? 0 : this.min;\r\n            this.setmin = false;\r\n            if (this.max == null) {\r\n                if (this.intervals[this.intervals.length-1][0] >= this.data[0][1]) {\r\n                    this.max = this.intervals[this.intervals.length-1][0];\r\n                    this.setmax = false;\r\n                }\r\n            }\r\n            else {\r\n                this.setmax = false;\r\n            }\r\n        }\r\n        \r\n        else {\r\n            // no ticks and no intervals supplied, put needle in middle\r\n            this.min = (this.min == null) ? 0 : this.min;\r\n            this.setmin = false;\r\n            if (this.max == null) {\r\n                this.max = this.data[0][1] * 1.25;\r\n                this.setmax = true;\r\n            }\r\n            else {\r\n                this.setmax = false;\r\n            }\r\n        }\r\n    };\r\n    \r\n    $.jqplot.MeterGaugeRenderer.prototype.setGridData = function(plot) {\r\n        // set gridData property.  This will hold angle in radians of each data point.\r\n        var stack = [];\r\n        var td = [];\r\n        var sa = this.startAngle;\r\n        for (var i=0; i<this.data.length; i++){\r\n            stack.push(this.data[i][1]);\r\n            td.push([this.data[i][0]]);\r\n            if (i>0) {\r\n                stack[i] += stack[i-1];\r\n            }\r\n        }\r\n        var fact = Math.PI*2/stack[stack.length - 1];\r\n        \r\n        for (var i=0; i<stack.length; i++) {\r\n            td[i][1] = stack[i] * fact;\r\n        }\r\n        this.gridData = td;\r\n    };\r\n    \r\n    $.jqplot.MeterGaugeRenderer.prototype.makeGridData = function(data, plot) {\r\n        var stack = [];\r\n        var td = [];\r\n        var sa = this.startAngle;\r\n        for (var i=0; i<data.length; i++){\r\n            stack.push(data[i][1]);\r\n            td.push([data[i][0]]);\r\n            if (i>0) {\r\n                stack[i] += stack[i-1];\r\n            }\r\n        }\r\n        var fact = Math.PI*2/stack[stack.length - 1];\r\n        \r\n        for (var i=0; i<stack.length; i++) {\r\n            td[i][1] = stack[i] * fact;\r\n        }\r\n        return td;\r\n    };\r\n\r\n        \r\n    function getnmt(pos, interval, fact) {\r\n        var temp;\r\n        for (var i=pos.length-1; i>=0; i--) {\r\n            temp = interval/(pos[i] * Math.pow(10, fact));\r\n            if (temp == 4 || temp == 5) {\r\n                return temp - 1;\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n    \r\n    // called with scope of series\r\n    $.jqplot.MeterGaugeRenderer.prototype.draw = function (ctx, gd, options) {\r\n        var i;\r\n        var opts = (options != undefined) ? options : {};\r\n        // offset and direction of offset due to legend placement\r\n        var offx = 0;\r\n        var offy = 0;\r\n        var trans = 1;\r\n        if (options.legendInfo && options.legendInfo.placement == 'inside') {\r\n            var li = options.legendInfo;\r\n            switch (li.location) {\r\n                case 'nw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'w':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'sw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'ne':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'e':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'se':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'n':\r\n                    offy = li.height + li.yoffset;\r\n                    break;\r\n                case 's':\r\n                    offy = li.height + li.yoffset;\r\n                    trans = -1;\r\n                    break;\r\n                default:\r\n                    break;\r\n            }\r\n        }\r\n        \r\n        \r\n            \r\n        // pre-draw so can get its dimensions.\r\n        if (this.label) {\r\n            this._labelElem = $('<div class=\"jqplot-meterGauge-label\" style=\"position:absolute;\">'+this.label+'</div>');\r\n            this.canvas._elem.after(this._labelElem);\r\n        }\r\n        \r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        var cw = ctx.canvas.width;\r\n        var ch = ctx.canvas.height;\r\n        if (this.padding == null) {\r\n            this.padding = Math.round(Math.min(cw, ch)/30);\r\n        }\r\n        var w = cw - offx - 2 * this.padding;\r\n        var h = ch - offy - 2 * this.padding;\r\n        if (this.labelPosition == 'bottom' && this.label) {\r\n            h -= this._labelElem.outerHeight(true);\r\n        }\r\n        var mindim = Math.min(w,h);\r\n        var d = mindim;\r\n            \r\n        if (!this.diameter) {\r\n            if (this.semiCircular) {\r\n                if ( w >= 2*h) {\r\n                    if (!this.ringWidth) {\r\n                        this.ringWidth = 2*h/35;\r\n                    }\r\n                    this.needleThickness = this.needleThickness || 2+Math.pow(this.ringWidth, 0.8);\r\n                    this.innerPad = this.ringWidth/2 + this.needleThickness/2 + this.needlePad;\r\n                    this.diameter = 2 * (h - 2*this.innerPad);\r\n                }\r\n                else {\r\n                    if (!this.ringWidth) {\r\n                        this.ringWidth = w/35;\r\n                    }\r\n                    this.needleThickness = this.needleThickness || 2+Math.pow(this.ringWidth, 0.8);\r\n                    this.innerPad = this.ringWidth/2 + this.needleThickness/2 + this.needlePad;\r\n                    this.diameter = w - 2*this.innerPad - this.ringWidth - this.padding;\r\n                }\r\n                // center taking into account legend and over draw for gauge bottom below hub.\r\n                // this will be center of hub.\r\n                this._center = [(cw - trans * offx)/2 + trans * offx,  (ch + trans*offy - this.padding - this.ringWidth - this.innerPad)];\r\n            }\r\n            else {\r\n                if (!this.ringWidth) {\r\n                    this.ringWidth = d/35;\r\n                }\r\n                this.needleThickness = this.needleThickness || 2+Math.pow(this.ringWidth, 0.8);\r\n                this.innerPad = 0;\r\n                this.diameter = d - this.ringWidth;\r\n                // center in middle of canvas taking into account legend.\r\n                // will be center of hub.\r\n                this._center = [(cw-trans*offx)/2 + trans * offx, (ch-trans*offy)/2 + trans * offy];\r\n            }\r\n            if (this._labelElem && this.labelPosition == 'bottom') {\r\n                this._center[1] -= this._labelElem.outerHeight(true);\r\n            }\r\n            \r\n        }\r\n\r\n        this._radius = this.diameter/2;\r\n        \r\n        this.tickSpacing = 6000/this.diameter;\r\n        \r\n        if (!this.hubRadius) {\r\n            this.hubRadius = this.diameter/18;\r\n        }\r\n        \r\n        this.shadowOffset = 0.5 + this.ringWidth/9;\r\n        this.shadowWidth = this.ringWidth*1;\r\n        \r\n        this.tickPadding = 3 + Math.pow(this.diameter/20, 0.7);\r\n        this.tickOuterRadius = this._radius - this.ringWidth/2 - this.tickPadding;\r\n        this.tickLength = (this.showTicks) ? this._radius/13 : 0;\r\n        \r\n        if (this.ticks.length == 0) {\r\n            // no ticks, lets make some.\r\n            var max = this.max,\r\n                min = this.min,\r\n                setmax = this.setmax,\r\n                setmin = this.setmin,\r\n                ti = (max - min) * this.tickSpacing / this.span;\r\n            var tf = Math.floor(parseFloat((Math.log(ti)/Math.log(10)).toFixed(11)));\r\n            var tp = (ti/Math.pow(10, tf));\r\n            (tp > 2 && tp <= 2.5) ? tp = 2.5 : tp = Math.ceil(tp);\r\n            var t = this.tickPositions;\r\n            var tpindex, nt;\r\n    \r\n            for (i=0; i<t.length; i++) {\r\n                if (tp == t[i] || i && t[i-1] < tp && tp < t[i]) { \r\n                    ti = t[i]*Math.pow(10, tf);\r\n                    tpindex = i;\r\n                }\r\n            }\r\n        \r\n            for (i=0; i<t.length; i++) {\r\n                if (tp == t[i] || i && t[i-1] < tp && tp < t[i]) { \r\n                    ti = t[i]*Math.pow(10, tf);\r\n                    nt = Math.ceil((max - min) / ti);\r\n                }\r\n            }\r\n        \r\n            // both max and min are free\r\n            if (setmax && setmin) {\r\n                var tmin = (min > 0) ? min - min % ti : min - min % ti - ti;\r\n                if (!this.forceZero) {\r\n                    var diff = Math.min(min - tmin, 0.8*ti);\r\n                    var ntp = Math.floor(diff/t[tpindex]);\r\n                    if (ntp > 1) {\r\n                        tmin = tmin + t[tpindex] * (ntp-1);\r\n                        if (parseInt(tmin, 10) != tmin && parseInt(tmin-t[tpindex], 10) == tmin-t[tpindex]) {\r\n                            tmin = tmin - t[tpindex];\r\n                        }\r\n                    }\r\n                }\r\n                if (min == tmin) {\r\n                    min -= ti;\r\n                }\r\n                else {\r\n                    // tmin should always be lower than dataMin\r\n                    if (min - tmin > 0.23*ti) {\r\n                        min = tmin;\r\n                    }\r\n                    else {\r\n                        min = tmin -ti;\r\n                        nt += 1;\r\n                    }\r\n                }\r\n                nt += 1;\r\n                var tmax = min + (nt - 1) * ti;\r\n                if (max >= tmax) { \r\n                    tmax += ti;\r\n                    nt += 1;\r\n                }\r\n                // now tmax should always be mroe than dataMax\r\n                if (tmax - max < 0.23*ti) { \r\n                    tmax += ti;\r\n                    nt += 1;\r\n                }\r\n                this.max = max = tmax;\r\n                this.min = min;    \r\n\r\n                this.tickInterval = ti;\r\n                this.numberTicks = nt;\r\n                var it;\r\n                for (i=0; i<nt; i++) {\r\n                    it = parseFloat((min+i*ti).toFixed(11));\r\n                    this.ticks.push([it, it]);\r\n                }\r\n                this.max = this.ticks[nt-1][1];\r\n            \r\n                this.tickFactor = tf;      \r\n                // determine number of minor ticks\r\n\r\n                this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor);     \r\n        \r\n                if (!this.numberMinorTicks) {\r\n                    this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1);\r\n                }\r\n            }\r\n            // max is free, min is fixed\r\n            else if (setmax) {\r\n                var tmax = min + (nt - 1) * ti;\r\n                if (max >= tmax) {\r\n                    max = tmax + ti;\r\n                    nt += 1;\r\n                }\r\n                else {\r\n                    max = tmax;\r\n                }\r\n\r\n                this.tickInterval = this.tickInterval || ti;\r\n                this.numberTicks = this.numberTicks || nt;\r\n                var it;\r\n                for (i=0; i<this.numberTicks; i++) {\r\n                    it = parseFloat((min+i*this.tickInterval).toFixed(11));\r\n                    this.ticks.push([it, it]);\r\n                }\r\n                this.max = this.ticks[this.numberTicks-1][1];\r\n            \r\n                this.tickFactor = tf;\r\n                // determine number of minor ticks\r\n                this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor);\r\n        \r\n                if (!this.numberMinorTicks) {\r\n                    this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1);\r\n                }\r\n            }\r\n            \r\n            // not setting max or min\r\n            if (!setmax && !setmin) {\r\n                var range = this.max - this.min;\r\n                tf = Math.floor(parseFloat((Math.log(range)/Math.log(10)).toFixed(11))) - 1;\r\n                var nticks = [5,6,4,7,3,8,9,10,2], res, numticks, nonSigDigits=0, sigRange;\r\n                // check to see how many zeros are at the end of the range\r\n                if (range > 1) {\r\n                    var rstr = String(range);\r\n                    if (rstr.search(/\\./) == -1) {\r\n                         var pos = rstr.search(/0+$/);\r\n                         nonSigDigits = (pos > 0) ? rstr.length - pos - 1 : 0;\r\n                    }\r\n                }\r\n                sigRange = range/Math.pow(10, nonSigDigits);\r\n                for (i=0; i<nticks.length; i++) {\r\n                    res = sigRange/(nticks[i]-1);\r\n                    if (res == parseInt(res, 10)) {\r\n                        this.numberTicks = nticks[i];\r\n                        this.tickInterval = range/(this.numberTicks-1);\r\n                        this.tickFactor = tf+1;\r\n                        break;\r\n                    }\r\n                }\r\n                var it;\r\n                for (i=0; i<this.numberTicks; i++) {\r\n                    it = parseFloat((this.min+i*this.tickInterval).toFixed(11));\r\n                    this.ticks.push([it, it]);\r\n                }\r\n                // determine number of minor ticks\r\n                this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor);\r\n        \r\n                if (!this.numberMinorTicks) {\r\n                    this.numberMinorTicks = getnmt(this.tickPositions, this.tickInterval, this.tickFactor-1);\r\n                }\r\n                \r\n                if (!this.numberMinorTicks) {\r\n                    this.numberMinorTicks = 1;\r\n                    var nums = [4, 5, 3, 6, 2];\r\n                    for (i=0; i<5; i++) {\r\n                        var temp = this.tickInterval/nums[i];\r\n                        if (temp == parseInt(temp, 10)) {\r\n                            this.numberMinorTicks = nums[i]-1;\r\n                            break;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        \r\n\r\n        var r = this._radius,\r\n            sa = this.startAngle,\r\n            ea = this.endAngle,       \r\n            pi = Math.PI,\r\n            hpi = Math.PI/2;\r\n            \r\n        if (this.semiCircular) {\r\n            var overAngle = Math.atan(this.innerPad/r),\r\n                outersa = this.outerStartAngle = sa - overAngle,\r\n                outerea = this.outerEndAngle = ea + overAngle,\r\n                hubsa = this.hubStartAngle = sa - Math.atan(this.innerPad/this.hubRadius*2),\r\n                hubea = this.hubEndAngle = ea + Math.atan(this.innerPad/this.hubRadius*2);\r\n\r\n            ctx.save();            \r\n            \r\n            ctx.translate(this._center[0], this._center[1]);\r\n            ctx.lineJoin = \"round\";\r\n            ctx.lineCap = \"round\";\r\n            \r\n            // draw the innerbackground\r\n            ctx.save();\r\n            ctx.beginPath();  \r\n            ctx.fillStyle = this.background;\r\n            ctx.arc(0, 0, r, outersa, outerea, false);\r\n            ctx.closePath();\r\n            ctx.fill();\r\n            ctx.restore();\r\n            \r\n            // draw the shadow\r\n            // the outer ring.\r\n            var shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';\r\n            ctx.save();\r\n            for (var i=0; i<this.shadowDepth; i++) {\r\n                ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));\r\n                ctx.beginPath();  \r\n                ctx.strokeStyle = shadowColor;\r\n                ctx.lineWidth = this.shadowWidth;\r\n                ctx.arc(0 ,0, r, outersa, outerea, false);\r\n                ctx.closePath();\r\n                ctx.stroke();\r\n            }\r\n            ctx.restore();\r\n            \r\n            // the inner hub.\r\n            ctx.save();\r\n            var tempd = parseInt((this.shadowDepth+1)/2, 10);\r\n            for (var i=0; i<tempd; i++) {\r\n                ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));\r\n                ctx.beginPath();  \r\n                ctx.fillStyle = shadowColor;\r\n                ctx.arc(0 ,0, this.hubRadius, hubsa, hubea, false);\r\n                ctx.closePath();\r\n                ctx.fill();\r\n            }\r\n            ctx.restore();\r\n            \r\n            // draw the outer ring.\r\n            ctx.save();\r\n            ctx.beginPath();  \r\n            ctx.strokeStyle = this.ringColor;\r\n            ctx.lineWidth = this.ringWidth;\r\n            ctx.arc(0 ,0, r, outersa, outerea, false);\r\n            ctx.closePath();\r\n            ctx.stroke();\r\n            ctx.restore();\r\n            \r\n            // draw the hub\r\n            \r\n            ctx.save();\r\n            ctx.beginPath();  \r\n            ctx.fillStyle = this.ringColor;\r\n            ctx.arc(0 ,0, this.hubRadius,hubsa, hubea, false);\r\n            ctx.closePath();\r\n            ctx.fill();\r\n            ctx.restore();\r\n            \r\n            // draw the ticks\r\n            if (this.showTicks) {\r\n                ctx.save();\r\n                var orad = this.tickOuterRadius,\r\n                    tl = this.tickLength,\r\n                    mtl = tl/2,\r\n                    nmt = this.numberMinorTicks,\r\n                    ts = this.span * Math.PI / 180 / (this.ticks.length-1),\r\n                    mts = ts/(nmt + 1);\r\n                \r\n                for (i = 0; i<this.ticks.length; i++) {\r\n                    ctx.beginPath();\r\n                    ctx.lineWidth = 1.5 + this.diameter/360;\r\n                    ctx.strokeStyle = this.ringColor;\r\n                    var wps = ts*i+sa;\r\n                    ctx.moveTo(-orad * Math.cos(ts*i+sa), orad * Math.sin(ts*i+sa));\r\n                    ctx.lineTo(-(orad-tl) * Math.cos(ts*i+sa), (orad - tl) * Math.sin(ts*i+sa));\r\n                    this._tickPoints.push([(orad-tl) * Math.cos(ts*i+sa) + this._center[0] + this.canvas._offsets.left, (orad - tl) * Math.sin(ts*i+sa) + this._center[1] + this.canvas._offsets.top, ts*i+sa]);\r\n                    ctx.stroke();\r\n                    ctx.lineWidth = 1.0 + this.diameter/440;\r\n                    if (i<this.ticks.length-1) {\r\n                        for (var j=1; j<=nmt; j++) {\r\n                            ctx.beginPath();\r\n                            ctx.moveTo(-orad * Math.cos(ts*i+mts*j+sa), orad * Math.sin(ts*i+mts*j+sa));\r\n                            ctx.lineTo(-(orad-mtl) * Math.cos(ts*i+mts*j+sa), (orad-mtl) * Math.sin(ts*i+mts*j+sa));\r\n                            ctx.stroke();\r\n                        }   \r\n                    }\r\n                }\r\n                ctx.restore();\r\n            }\r\n            \r\n            // draw the tick labels\r\n            if (this.showTickLabels) {\r\n                var elem, l, t, ew, eh, dim, maxdim=0;\r\n                var tp = this.tickPadding * (1 - 1/(this.diameter/80+1));\r\n                for (i=0; i<this.ticks.length; i++) {\r\n                    elem = $('<div class=\"jqplot-meterGauge-tick\" style=\"position:absolute;\">'+this.ticks[i][1]+'</div>');\r\n                    this.canvas._elem.after(elem);\r\n                    ew = elem.outerWidth(true);\r\n                    eh = elem.outerHeight(true);\r\n                    l = this._tickPoints[i][0] - ew * (this._tickPoints[i][2]-Math.PI)/Math.PI - tp * Math.cos(this._tickPoints[i][2]);\r\n                    t = this._tickPoints[i][1] - eh/2 + eh/2 * Math.pow(Math.abs((Math.sin(this._tickPoints[i][2]))), 0.5) + tp/3 * Math.pow(Math.abs((Math.sin(this._tickPoints[i][2]))), 0.5) ;\r\n                    // t = this._tickPoints[i][1] - eh/2 - eh/2 * Math.sin(this._tickPoints[i][2]) - tp/2 * Math.sin(this._tickPoints[i][2]);\r\n                    elem.css({left:l, top:t, color: this.tickColor});\r\n                    dim  = ew*Math.cos(this._tickPoints[i][2]) + eh*Math.sin(Math.PI/2+this._tickPoints[i][2]/2);\r\n                    maxdim = (dim > maxdim) ? dim : maxdim;\r\n                }\r\n            }\r\n            \r\n            // draw the gauge label\r\n            if (this.label && this.labelPosition == 'inside') {\r\n                var l = this._center[0] + this.canvas._offsets.left;\r\n                var tp = this.tickPadding * (1 - 1/(this.diameter/80+1));\r\n                var t = 0.5*(this._center[1] + this.canvas._offsets.top - this.hubRadius) + 0.5*(this._center[1] + this.canvas._offsets.top - this.tickOuterRadius + this.tickLength + tp) + this.labelHeightAdjust;\r\n                // this._labelElem = $('<div class=\"jqplot-meterGauge-label\" style=\"position:absolute;\">'+this.label+'</div>');\r\n                // this.canvas._elem.after(this._labelElem);\r\n                l -= this._labelElem.outerWidth(true)/2;\r\n                t -= this._labelElem.outerHeight(true)/2;\r\n                this._labelElem.css({left:l, top:t});\r\n            }\r\n            \r\n            else if (this.label && this.labelPosition == 'bottom') {\r\n                var l = this._center[0] + this.canvas._offsets.left - this._labelElem.outerWidth(true)/2;\r\n                var t = this._center[1] + this.canvas._offsets.top + this.innerPad + this.ringWidth + this.padding + this.labelHeightAdjust;\r\n                this._labelElem.css({left:l, top:t});\r\n                \r\n            }\r\n            \r\n            // draw the intervals\r\n            \r\n            ctx.save();\r\n            var inner = this.intervalInnerRadius || this.hubRadius * 1.5;\r\n            if (this.intervalOuterRadius == null) {\r\n                if (this.showTickLabels) {\r\n                    var outer = (this.tickOuterRadius - this.tickLength - this.tickPadding - this.diameter/8);\r\n                }\r\n                else {\r\n                    var outer = (this.tickOuterRadius - this.tickLength - this.diameter/16);\r\n                }\r\n            }\r\n            else {\r\n                var outer = this.intervalOuterRadius;\r\n            }\r\n            var range = this.max - this.min;\r\n            var intrange = this.intervals[this.intervals.length-1] - this.min;\r\n            var start, end, span = this.span*Math.PI/180;\r\n            for (i=0; i<this.intervals.length; i++) {\r\n                start = (i == 0) ? sa : sa + (this.intervals[i-1][0] - this.min)*span/range;\r\n                if (start < 0) {\r\n                    start = 0;\r\n                }\r\n                end = sa + (this.intervals[i][0] - this.min)*span/range;\r\n                if (end < 0) {\r\n                    end = 0;\r\n                }\r\n                ctx.beginPath();\r\n                ctx.fillStyle = this.intervals[i][2];\r\n                ctx.arc(0, 0, inner, start, end, false);\r\n                ctx.lineTo(outer*Math.cos(end), outer*Math.sin(end));\r\n                ctx.arc(0, 0, outer, end, start, true);\r\n                ctx.lineTo(inner*Math.cos(start), inner*Math.sin(start));\r\n                ctx.closePath();\r\n                ctx.fill();\r\n            }\r\n            ctx.restore();\r\n            \r\n            // draw the needle\r\n            var datapoint = this.data[0][1];\r\n            var dataspan = this.max - this.min;\r\n            if (this.pegNeedle) {\r\n                if (this.data[0][1] > this.max + dataspan*3/this.span) {\r\n                    datapoint = this.max + dataspan*3/this.span;\r\n                }\r\n                if (this.data[0][1] < this.min - dataspan*3/this.span) {\r\n                    datapoint = this.min - dataspan*3/this.span;\r\n                }\r\n            }\r\n            var dataang = (datapoint - this.min)/dataspan * this.span * Math.PI/180 + this.startAngle;\r\n            \r\n            \r\n            ctx.save();\r\n            ctx.beginPath();\r\n            ctx.fillStyle = this.ringColor;\r\n            ctx.strokeStyle = this.ringColor;\r\n            this.needleLength = (this.tickOuterRadius - this.tickLength) * 0.85;\r\n            this.needleThickness = (this.needleThickness < 2) ? 2 : this.needleThickness;\r\n            var endwidth = this.needleThickness * 0.4;\r\n\r\n            \r\n            var dl = this.needleLength/10;\r\n            var dt = (this.needleThickness - endwidth)/10;\r\n            var templ;\r\n            for (var i=0; i<10; i++) {\r\n                templ = this.needleThickness - i*dt;\r\n                ctx.moveTo(dl*i*Math.cos(dataang), dl*i*Math.sin(dataang));\r\n                ctx.lineWidth = templ;\r\n                ctx.lineTo(dl*(i+1)*Math.cos(dataang), dl*(i+1)*Math.sin(dataang));\r\n                ctx.stroke();\r\n            }\r\n            \r\n            ctx.restore();\r\n        }\r\n        else {\r\n            this._center = [(cw - trans * offx)/2 + trans * offx, (ch - trans*offy)/2 + trans * offy];\r\n        }               \r\n    };\r\n    \r\n    $.jqplot.MeterGaugeAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.MeterGaugeAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.MeterGaugeAxisRenderer.prototype.constructor = $.jqplot.MeterGaugeAxisRenderer;\r\n        \r\n    \r\n    // There are no traditional axes on a gauge chart.  We just need to provide\r\n    // dummy objects with properties so the plot will render.\r\n    // called with scope of axis object.\r\n    $.jqplot.MeterGaugeAxisRenderer.prototype.init = function(options){\r\n        //\r\n        this.tickRenderer = $.jqplot.MeterGaugeTickRenderer;\r\n        $.extend(true, this, options);\r\n        // I don't think I'm going to need _dataBounds here.\r\n        // have to go Axis scaling in a way to fit chart onto plot area\r\n        // and provide u2p and p2u functionality for mouse cursor, etc.\r\n        // for convienence set _dataBounds to 0 and 100 and\r\n        // set min/max to 0 and 100.\r\n        this._dataBounds = {min:0, max:100};\r\n        this.min = 0;\r\n        this.max = 100;\r\n        this.showTicks = false;\r\n        this.ticks = [];\r\n        this.showMark = false;\r\n        this.show = false; \r\n    };\r\n    \r\n    $.jqplot.MeterGaugeLegendRenderer = function(){\r\n        $.jqplot.TableLegendRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.MeterGaugeLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();\r\n    $.jqplot.MeterGaugeLegendRenderer.prototype.constructor = $.jqplot.MeterGaugeLegendRenderer;\r\n    \r\n    /**\r\n     * Class: $.jqplot.MeterGaugeLegendRenderer\r\n     *Meter gauges don't typically have a legend, this overrides the default legend renderer.\r\n     */\r\n    $.jqplot.MeterGaugeLegendRenderer.prototype.init = function(options) {\r\n        // Maximum number of rows in the legend.  0 or null for unlimited.\r\n        this.numberRows = null;\r\n        // Maximum number of columns in the legend.  0 or null for unlimited.\r\n        this.numberColumns = null;\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    // called with context of legend\r\n    $.jqplot.MeterGaugeLegendRenderer.prototype.draw = function() {\r\n        if (this.show) {\r\n            var series = this._series;\r\n            var ss = 'position:absolute;';\r\n            ss += (this.background) ? 'background:'+this.background+';' : '';\r\n            ss += (this.border) ? 'border:'+this.border+';' : '';\r\n            ss += (this.fontSize) ? 'font-size:'+this.fontSize+';' : '';\r\n            ss += (this.fontFamily) ? 'font-family:'+this.fontFamily+';' : '';\r\n            ss += (this.textColor) ? 'color:'+this.textColor+';' : '';\r\n            ss += (this.marginTop != null) ? 'margin-top:'+this.marginTop+';' : '';\r\n            ss += (this.marginBottom != null) ? 'margin-bottom:'+this.marginBottom+';' : '';\r\n            ss += (this.marginLeft != null) ? 'margin-left:'+this.marginLeft+';' : '';\r\n            ss += (this.marginRight != null) ? 'margin-right:'+this.marginRight+';' : '';\r\n            this._elem = $('<table class=\"jqplot-table-legend\" style=\"'+ss+'\"></table>');\r\n            // MeterGauge charts legends don't go by number of series, but by number of data points\r\n            // in the series.  Refactor things here for that.\r\n            \r\n            var pad = false, \r\n                reverse = false,\r\n                nr, nc;\r\n            var s = series[0];\r\n            \r\n            if (s.show) {\r\n                var pd = s.data;\r\n                if (this.numberRows) {\r\n                    nr = this.numberRows;\r\n                    if (!this.numberColumns){\r\n                        nc = Math.ceil(pd.length/nr);\r\n                    }\r\n                    else{\r\n                        nc = this.numberColumns;\r\n                    }\r\n                }\r\n                else if (this.numberColumns) {\r\n                    nc = this.numberColumns;\r\n                    nr = Math.ceil(pd.length/this.numberColumns);\r\n                }\r\n                else {\r\n                    nr = pd.length;\r\n                    nc = 1;\r\n                }\r\n                \r\n                var i, j, tr, td1, td2, lt, rs, color;\r\n                var idx = 0;    \r\n                \r\n                for (i=0; i<nr; i++) {\r\n                    if (reverse){\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').prependTo(this._elem);\r\n                    }\r\n                    else{\r\n                        tr = $('<tr class=\"jqplot-table-legend\"></tr>').appendTo(this._elem);\r\n                    }\r\n                    for (j=0; j<nc; j++) {\r\n                        if (idx < pd.length){\r\n                            // debugger\r\n                            lt = this.labels[idx] || pd[idx][0].toString();\r\n                            color = s.color;\r\n                            if (!reverse){\r\n                                if (i>0){\r\n                                    pad = true;\r\n                                }\r\n                                else{\r\n                                    pad = false;\r\n                                }\r\n                            }\r\n                            else{\r\n                                if (i == nr -1){\r\n                                    pad = false;\r\n                                }\r\n                                else{\r\n                                    pad = true;\r\n                                }\r\n                            }\r\n                            rs = (pad) ? this.rowSpacing : '0';\r\n                \r\n                            td1 = $('<td class=\"jqplot-table-legend\" style=\"text-align:center;padding-top:'+rs+';\">'+\r\n                                '<div><div class=\"jqplot-table-legend-swatch\" style=\"border-color:'+color+';\"></div>'+\r\n                                '</div></td>');\r\n                            td2 = $('<td class=\"jqplot-table-legend\" style=\"padding-top:'+rs+';\"></td>');\r\n                            if (this.escapeHtml){\r\n                                td2.text(lt);\r\n                            }\r\n                            else {\r\n                                td2.html(lt);\r\n                            }\r\n                            if (reverse) {\r\n                                td2.prependTo(tr);\r\n                                td1.prependTo(tr);\r\n                            }\r\n                            else {\r\n                                td1.appendTo(tr);\r\n                                td2.appendTo(tr);\r\n                            }\r\n                            pad = true;\r\n                        }\r\n                        idx++;\r\n                    }   \r\n                }\r\n            }\r\n        }\r\n        return this._elem;                \r\n    };\r\n    \r\n    \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        // debugger\r\n        options = options || {};\r\n        options.axesDefaults = options.axesDefaults || {};\r\n        options.legend = options.legend || {};\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        options.grid = options.grid || {};\r\n           \r\n        // only set these if there is a gauge series\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer == $.jqplot.MeterGaugeRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer == $.jqplot.MeterGaugeRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.MeterGaugeAxisRenderer;\r\n            options.legend.renderer = $.jqplot.MeterGaugeLegendRenderer;\r\n            options.legend.preDraw = true;\r\n            options.grid.background = options.grid.background || 'white';\r\n            options.grid.drawGridlines = false;\r\n            options.grid.borderWidth = (options.grid.borderWidth != null) ? options.grid.borderWidth : 0;\r\n            options.grid.shadow = (options.grid.shadow != null) ? options.grid.shadow : false;\r\n        }\r\n    }\r\n    \r\n    // called with scope of plot\r\n    function postParseOptions(options) {\r\n        //\r\n    }\r\n    \r\n    $.jqplot.preInitHooks.push(preInit);\r\n    $.jqplot.postParseOptionsHooks.push(postParseOptions);\r\n    \r\n    $.jqplot.MeterGaugeTickRenderer = function() {\r\n        $.jqplot.AxisTickRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.MeterGaugeTickRenderer.prototype = new $.jqplot.AxisTickRenderer();\r\n    $.jqplot.MeterGaugeTickRenderer.prototype.constructor = $.jqplot.MeterGaugeTickRenderer;\r\n    \r\n})(jQuery);\r\n    \r\n    \r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.mobile.js",
    "content": "/**\r\n * jqplot.jquerymobile plugin\r\n * jQuery Mobile virtual event support.\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2011 Takashi Okamoto\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n */\r\n(function($) {\r\n    function postInit(target, data, options){\r\n        this.bindCustomEvents = function() {\r\n            this.eventCanvas._elem.bind('vclick', {plot:this}, this.onClick);\r\n            this.eventCanvas._elem.bind('dblclick', {plot:this}, this.onDblClick);\r\n            this.eventCanvas._elem.bind('taphold', {plot:this}, this.onDblClick);\r\n            this.eventCanvas._elem.bind('vmousedown', {plot:this}, this.onMouseDown);\r\n            this.eventCanvas._elem.bind('vmousemove', {plot:this}, this.onMouseMove);\r\n            this.eventCanvas._elem.bind('mouseenter', {plot:this}, this.onMouseEnter);\r\n            this.eventCanvas._elem.bind('mouseleave', {plot:this}, this.onMouseLeave);\r\n            if (this.captureRightClick) {\r\n                this.eventCanvas._elem.bind('vmouseup', {plot:this}, this.onRightClick);\r\n                this.eventCanvas._elem.get(0).oncontextmenu = function() {\r\n                    return false;\r\n                };\r\n            }\r\n            else {\r\n                this.eventCanvas._elem.bind('vmouseup', {plot:this}, this.onMouseUp);\r\n            }\r\n        };\r\n        this.plugins.mobile = true;\r\n    }\r\n    $.jqplot.postInitHooks.push(postInit);\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.ohlcRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.OHLCRenderer\r\n     * jqPlot Plugin to draw Open Hi Low Close, Candlestick and Hi Low Close charts.\r\n     * \r\n     * To use this plugin, include the renderer js file in \r\n     * your source:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.ohlcRenderer.js\"></script>\r\n     * \r\n     * You will most likely want to use a date axis renderer\r\n     * for the x axis also, so include the date axis render js file also:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.dateAxisRenderer.js\"></script>\r\n     * \r\n     * Then you set the renderer in the series options on your plot:\r\n     * \r\n     * > series: [{renderer:$.jqplot.OHLCRenderer}]\r\n     * \r\n     * For OHLC and candlestick charts, data should be specified\r\n     * like so:\r\n     * \r\n     * > dat = [['07/06/2009',138.7,139.68,135.18,135.4], ['06/29/2009',143.46,144.66,139.79,140.02], ...]\r\n     * \r\n     * If the data array has only 4 values per point instead of 5,\r\n     * the renderer will create a Hi Low Close chart instead.  In that case,\r\n     * data should be supplied like:\r\n     * \r\n     * > dat = [['07/06/2009',139.68,135.18,135.4], ['06/29/2009',144.66,139.79,140.02], ...]\r\n     * \r\n     * To generate a candlestick chart instead of an OHLC chart,\r\n     * set the \"candlestick\" option to true:\r\n     * \r\n     * > series: [{renderer:$.jqplot.OHLCRenderer, rendererOptions:{candleStick:true}}],\r\n     * \r\n     */\r\n    $.jqplot.OHLCRenderer = function(){\r\n        // subclass line renderer to make use of some of its methods.\r\n        $.jqplot.LineRenderer.call(this);\r\n        // prop: candleStick\r\n        // true to render chart as candleStick.\r\n        // Must have an open price, cannot be a hlc chart.\r\n        this.candleStick = false;\r\n        // prop: tickLength\r\n        // length of the line in pixels indicating open and close price.\r\n        // Default will auto calculate based on plot width and \r\n        // number of points displayed.\r\n        this.tickLength = 'auto';\r\n        // prop: bodyWidth\r\n        // width of the candlestick body in pixels.  Default will auto calculate\r\n        // based on plot width and number of candlesticks displayed.\r\n        this.bodyWidth = 'auto';\r\n        // prop: openColor\r\n        // color of the open price tick mark.  Default is series color.\r\n        this.openColor = null;\r\n        // prop: closeColor\r\n        // color of the close price tick mark.  Default is series color.\r\n        this.closeColor = null;\r\n        // prop: wickColor\r\n        // color of the hi-lo line thorugh the candlestick body.\r\n        // Default is the series color.\r\n        this.wickColor = null;\r\n        // prop: fillUpBody\r\n        // true to render an \"up\" day (close price greater than open price)\r\n        // with a filled candlestick body.\r\n        this.fillUpBody = false;\r\n        // prop: fillDownBody\r\n        // true to render a \"down\" day (close price lower than open price)\r\n        // with a filled candlestick body.\r\n        this.fillDownBody = true;\r\n        // prop: upBodyColor\r\n        // Color of candlestick body of an \"up\" day.  Default is series color.\r\n        this.upBodyColor = null;\r\n        // prop: downBodyColor\r\n        // Color of candlestick body on a \"down\" day.  Default is series color.\r\n        this.downBodyColor = null;\r\n        // prop: hlc\r\n        // true if is a hi-low-close chart (no open price).\r\n        // This is determined automatically from the series data.\r\n        this.hlc = false;\r\n        // prop: lineWidth\r\n        // Width of the hi-low line and open/close ticks.\r\n        // Must be set in the rendererOptions for the series.\r\n        this.lineWidth = 1.5;\r\n        this._tickLength;\r\n        this._bodyWidth;\r\n    };\r\n    \r\n    $.jqplot.OHLCRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.OHLCRenderer.prototype.constructor = $.jqplot.OHLCRenderer;\r\n    \r\n    // called with scope of series.\r\n    $.jqplot.OHLCRenderer.prototype.init = function(options) {\r\n        options = options || {};\r\n        // lineWidth has to be set on the series, changes in renderer\r\n        // constructor have no effect.  set the default here\r\n        // if no renderer option for lineWidth is specified.\r\n        this.lineWidth = options.lineWidth || 1.5;\r\n        $.jqplot.LineRenderer.prototype.init.call(this, options);\r\n        this._type = 'ohlc';\r\n        // set the yaxis data bounds here to account for hi and low values\r\n        var db = this._yaxis._dataBounds;\r\n        var d = this._plotData;\r\n        // if data points have less than 5 values, force a hlc chart.\r\n        if (d[0].length < 5) {\r\n            this.renderer.hlc = true;\r\n\r\n            for (var j=0; j<d.length; j++) { \r\n                if (d[j][2] < db.min || db.min == null) {\r\n                    db.min = d[j][2];\r\n                }\r\n                if (d[j][1] > db.max || db.max == null) {\r\n                    db.max = d[j][1];\r\n                }             \r\n            }\r\n        }\r\n        else {\r\n            for (var j=0; j<d.length; j++) { \r\n                if (d[j][3] < db.min || db.min == null) {\r\n                    db.min = d[j][3];\r\n                }\r\n                if (d[j][2] > db.max || db.max == null) {\r\n                    db.max = d[j][2];\r\n                }             \r\n            }\r\n        }\r\n        \r\n    };\r\n    \r\n    // called within scope of series.\r\n    $.jqplot.OHLCRenderer.prototype.draw = function(ctx, gd, options) {\r\n        var d = this.data;\r\n        var xmin = this._xaxis.min;\r\n        var xmax = this._xaxis.max;\r\n        // index of last value below range of plot.\r\n        var xminidx = 0;\r\n        // index of first value above range of plot.\r\n        var xmaxidx = d.length;\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var i, prevColor, ops, b, h, w, a, points;\r\n        var o;\r\n        var r = this.renderer;\r\n        var opts = (options != undefined) ? options : {};\r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        var fillAndStroke = (opts.fillAndStroke != undefined) ? opts.fillAndStroke : this.fillAndStroke;\r\n        r.bodyWidth = (opts.bodyWidth != undefined) ? opts.bodyWidth : r.bodyWidth;\r\n        r.tickLength = (opts.tickLength != undefined) ? opts.tickLength : r.tickLength;\r\n        ctx.save();\r\n        if (this.show) {\r\n            var x, open, hi, low, close;\r\n            // need to get widths based on number of points shown,\r\n            // not on total number of points.  Use the results \r\n            // to speed up drawing in next step.\r\n            for (var i=0; i<d.length; i++) {\r\n                if (d[i][0] < xmin) {\r\n                    xminidx = i;\r\n                }\r\n                else if (d[i][0] < xmax) {\r\n                    xmaxidx = i+1;\r\n                }\r\n            }\r\n\r\n            var dwidth = this.gridData[xmaxidx-1][0] - this.gridData[xminidx][0];\r\n            var nvisiblePoints = xmaxidx - xminidx;\r\n            try {\r\n                var dinterval = Math.abs(this._xaxis.series_u2p(parseInt(this._xaxis._intervalStats[0].sortedIntervals[0].interval, 10)) - this._xaxis.series_u2p(0)); \r\n            }\r\n\r\n            catch (e) {\r\n                var dinterval = dwidth / nvisiblePoints;\r\n            }\r\n            \r\n            if (r.candleStick) {\r\n                if (typeof(r.bodyWidth) == 'number') {\r\n                    r._bodyWidth = r.bodyWidth;\r\n                }\r\n                else {\r\n                    r._bodyWidth = Math.min(20, dinterval/1.65);\r\n                }\r\n            }\r\n            else {\r\n                if (typeof(r.tickLength) == 'number') {\r\n                    r._tickLength = r.tickLength;\r\n                }\r\n                else {\r\n                    r._tickLength = Math.min(10, dinterval/3.5);\r\n                }\r\n            }\r\n            \r\n            for (var i=xminidx; i<xmaxidx; i++) {\r\n                x = xp(d[i][0]);\r\n                if (r.hlc) {\r\n                    open = null;\r\n                    hi = yp(d[i][1]);\r\n                    low = yp(d[i][2]);\r\n                    close = yp(d[i][3]);\r\n                }\r\n                else {\r\n                    open = yp(d[i][1]);\r\n                    hi = yp(d[i][2]);\r\n                    low = yp(d[i][3]);\r\n                    close = yp(d[i][4]);\r\n                }\r\n                o = {};\r\n                if (r.candleStick && !r.hlc) {\r\n                    w = r._bodyWidth;\r\n                    a = x - w/2;\r\n                    // draw candle\r\n                    // determine if candle up or down\r\n                    // up, remember grid coordinates increase downward\r\n                    if (close < open) {\r\n                        // draw wick\r\n                        if (r.wickColor) {\r\n                            o.color = r.wickColor;\r\n                        }\r\n                        else if (r.downBodyColor) {\r\n                            o.color = r.upBodyColor;\r\n                        }\r\n                        ops = $.extend(true, {}, opts, o);\r\n                        r.shapeRenderer.draw(ctx, [[x, hi], [x, close]], ops); \r\n                        r.shapeRenderer.draw(ctx, [[x, open], [x, low]], ops); \r\n                        o = {};\r\n                        b = close;\r\n                        h = open - close;\r\n                        // if color specified, use it\r\n                        if (r.fillUpBody) {\r\n                            o.fillRect = true;\r\n                        }\r\n                        else {\r\n                            o.strokeRect = true;\r\n                            w = w - this.lineWidth;\r\n                            a = x - w/2;\r\n                        }\r\n                        if (r.upBodyColor) {\r\n                            o.color = r.upBodyColor;\r\n                            o.fillStyle = r.upBodyColor;\r\n                        }\r\n                        points = [a, b, w, h];\r\n                    }\r\n                    // down\r\n                    else if (close >  open) {\r\n                        // draw wick\r\n                        if (r.wickColor) {\r\n                            o.color = r.wickColor;\r\n                        }\r\n                        else if (r.downBodyColor) {\r\n                            o.color = r.downBodyColor;\r\n                        }\r\n                        ops = $.extend(true, {}, opts, o);\r\n                        r.shapeRenderer.draw(ctx, [[x, hi], [x, open]], ops); \r\n                        r.shapeRenderer.draw(ctx, [[x, close], [x, low]], ops);\r\n                         \r\n                        o = {};\r\n                        \r\n                        b = open;\r\n                        h = close - open;\r\n                        // if color specified, use it\r\n                        if (r.fillDownBody) {\r\n                            o.fillRect = true;\r\n                        }\r\n                        else {\r\n                            o.strokeRect = true;\r\n                            w = w - this.lineWidth;\r\n                            a = x - w/2;\r\n                        }\r\n                        if (r.downBodyColor) {\r\n                            o.color = r.downBodyColor;\r\n                            o.fillStyle = r.downBodyColor;\r\n                        }\r\n                        points = [a, b, w, h];\r\n                    }\r\n                    // even, open = close\r\n                    else  {\r\n                        // draw wick\r\n                        if (r.wickColor) {\r\n                            o.color = r.wickColor;\r\n                        }\r\n                        ops = $.extend(true, {}, opts, o);\r\n                        r.shapeRenderer.draw(ctx, [[x, hi], [x, low]], ops); \r\n                        o = {};\r\n                        o.fillRect = false;\r\n                        o.strokeRect = false;\r\n                        a = [x - w/2, open];\r\n                        b = [x + w/2, close];\r\n                        w = null;\r\n                        h = null;\r\n                        points = [a, b];\r\n                    }\r\n                    ops = $.extend(true, {}, opts, o);\r\n                    r.shapeRenderer.draw(ctx, points, ops);\r\n                }\r\n                else {\r\n                    prevColor = opts.color;\r\n                    if (r.openColor) {\r\n                        opts.color = r.openColor;\r\n                    }\r\n                    // draw open tick\r\n                    if (!r.hlc) {\r\n                        r.shapeRenderer.draw(ctx, [[x-r._tickLength, open], [x, open]], opts);    \r\n                    }\r\n                    opts.color = prevColor;\r\n                    // draw wick\r\n                    if (r.wickColor) {\r\n                        opts.color = r.wickColor;\r\n                    }\r\n                    r.shapeRenderer.draw(ctx, [[x, hi], [x, low]], opts); \r\n                    opts.color  = prevColor;\r\n                    // draw close tick\r\n                    if (r.closeColor) {\r\n                        opts.color = r.closeColor;\r\n                    }\r\n                    r.shapeRenderer.draw(ctx, [[x, close], [x+r._tickLength, close]], opts); \r\n                    opts.color = prevColor;\r\n                }\r\n            }\r\n        }\r\n        \r\n        ctx.restore();\r\n    };  \r\n    \r\n    $.jqplot.OHLCRenderer.prototype.drawShadow = function(ctx, gd, options) {\r\n        // This is a no-op, shadows drawn with lines.\r\n    };\r\n    \r\n    // called with scope of plot.\r\n    $.jqplot.OHLCRenderer.checkOptions = function(target, data, options) {\r\n        // provide some sensible highlighter options by default\r\n        // These aren't good for hlc, only for ohlc or candlestick\r\n        if (!options.highlighter) {\r\n            options.highlighter = {\r\n                showMarker:false,\r\n                tooltipAxes: 'y',\r\n                yvalues: 4,\r\n                formatString:'<table class=\"jqplot-highlighter\"><tr><td>date:</td><td>%s</td></tr><tr><td>open:</td><td>%s</td></tr><tr><td>hi:</td><td>%s</td></tr><tr><td>low:</td><td>%s</td></tr><tr><td>close:</td><td>%s</td></tr></table>'\r\n            };\r\n        }\r\n    };\r\n    \r\n    //$.jqplot.preInitHooks.push($.jqplot.OHLCRenderer.checkOptions);\r\n    \r\n})(jQuery);    \r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.pieRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    /**\r\n     * Class: $.jqplot.PieRenderer\r\n     * Plugin renderer to draw a pie chart.\r\n     * x values, if present, will be used as slice labels.\r\n     * y values give slice size.\r\n     * \r\n     * To use this renderer, you need to include the \r\n     * pie renderer plugin, for example:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.pieRenderer.js\"></script>\r\n     * \r\n     * Properties described here are passed into the $.jqplot function\r\n     * as options on the series renderer.  For example:\r\n     * \r\n     * > plot2 = $.jqplot('chart2', [s1, s2], {\r\n     * >     seriesDefaults: {\r\n     * >         renderer:$.jqplot.PieRenderer,\r\n     * >         rendererOptions:{\r\n     * >              sliceMargin: 2,\r\n     * >              startAngle: -90\r\n     * >          }\r\n     * >      }\r\n     * > });\r\n     * \r\n     * A pie plot will trigger events on the plot target\r\n     * according to user interaction.  All events return the event object,\r\n     * the series index, the point (slice) index, and the point data for \r\n     * the appropriate slice.\r\n     * \r\n     * 'jqplotDataMouseOver' - triggered when user mouseing over a slice.\r\n     * 'jqplotDataHighlight' - triggered the first time user mouses over a slice,\r\n     *   if highlighting is enabled.\r\n     * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of\r\n     *   a highlighted slice.\r\n     * 'jqplotLegendHighlight' - triggered the first time user mouses over a legend,\r\n     *   if highlighting is enabled.\r\n     * 'jqplotLegendUnhighlight' - triggered when a user moves the mouse out of\r\n     *   a highlighted legend.\r\n     * 'jqplotDataClick' - triggered when the user clicks on a slice.\r\n     * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if\r\n     * the \"captureRightClick\" option is set to true on the plot.\r\n     */\r\n    $.jqplot.PieRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer;\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.PieRenderer.prototype.init = function(options, plot) {\r\n        // Group: Properties\r\n        //\r\n        // prop: diameter\r\n        // Outer diameter of the pie, auto computed by default\r\n        this.diameter = null;\r\n        // prop: padding\r\n        // padding between the pie and plot edges, legend, etc.\r\n        this.padding = 20;\r\n        // prop: sliceMargin\r\n        // angular spacing between pie slices in degrees.\r\n        this.sliceMargin = 0;\r\n        // prop: fill\r\n        // true or false, whether to fil the slices.\r\n        this.fill = true;\r\n        // prop: shadowOffset\r\n        // offset of the shadow from the slice and offset of \r\n        // each succesive stroke of the shadow from the last.\r\n        this.shadowOffset = 2;\r\n        // prop: shadowAlpha\r\n        // transparency of the shadow (0 = transparent, 1 = opaque)\r\n        this.shadowAlpha = 0.07;\r\n        // prop: shadowDepth\r\n        // number of strokes to apply to the shadow, \r\n        // each stroke offset shadowOffset from the last.\r\n        this.shadowDepth = 5;\r\n        // prop: highlightMouseOver\r\n        // True to highlight slice when moused over.\r\n        // This must be false to enable highlightMouseDown to highlight when clicking on a slice.\r\n        this.highlightMouseOver = true;\r\n        // prop: highlightMouseDown\r\n        // True to highlight when a mouse button is pressed over a slice.\r\n        // This will be disabled if highlightMouseOver is true.\r\n        this.highlightMouseDown = false;\r\n        // prop: highlightColors\r\n        // an array of colors to use when highlighting a slice.\r\n        this.highlightColors = [];\r\n        // prop: dataLabels\r\n        // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices.\r\n        // Defaults to percentage of each pie slice.\r\n        this.dataLabels = 'percent';\r\n        // prop: showDataLabels\r\n        // true to show data labels on slices.\r\n        this.showDataLabels = false;\r\n        // prop: dataLabelFormatString\r\n        // Format string for data labels.  If none, '%s' is used for \"label\" and for arrays, '%d' for value and '%d%%' for percentage.\r\n        this.dataLabelFormatString = null;\r\n        // prop: dataLabelThreshold\r\n        // Threshhold in percentage (0-100) of pie area, below which no label will be displayed.\r\n        // This applies to all label types, not just to percentage labels.\r\n        this.dataLabelThreshold = 3;\r\n        // prop: dataLabelPositionFactor\r\n        // A Multiplier (0-1) of the pie radius which controls position of label on slice.\r\n        // Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie.\r\n        this.dataLabelPositionFactor = 0.52;\r\n        // prop: dataLabelNudge\r\n        // Number of pixels to slide the label away from (+) or toward (-) the center of the pie.\r\n        this.dataLabelNudge = 2;\r\n        // prop: dataLabelCenterOn\r\n        // True to center the data label at its position.\r\n        // False to set the inside facing edge of the label at its position.\r\n        this.dataLabelCenterOn = true;\r\n        // prop: startAngle\r\n        // Angle to start drawing pie in degrees.  \r\n        // According to orientation of canvas coordinate system:\r\n        // 0 = on the positive x axis\r\n        // -90 = on the positive y axis.\r\n        // 90 = on the negaive y axis.\r\n        // 180 or - 180 = on the negative x axis.\r\n        this.startAngle = 0;\r\n        this.tickRenderer = $.jqplot.PieTickRenderer;\r\n        // prop: showSlice\r\n        // Array for whether the pie chart slice for a data element should be displayed.\r\n        // Containsg true or false for each data element.  If not specified, defaults to true.\r\n        this.showSlice = [];\r\n        // Used as check for conditions where pie shouldn't be drawn.\r\n        this._drawData = true;\r\n        this._type = 'pie';\r\n        \r\n        // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver\r\n        if (options.highlightMouseDown && options.highlightMouseOver == null) {\r\n            options.highlightMouseOver = false;\r\n        }\r\n        \r\n        $.extend(true, this, options);\r\n\r\n        if (this.sliceMargin < 0) {\r\n            this.sliceMargin = 0;\r\n        }\r\n\r\n        this._diameter = null;\r\n        this._radius = null;\r\n        // array of [start,end] angles arrays, one for each slice.  In radians.\r\n        this._sliceAngles = [];\r\n        // index of the currenty highlighted point, if any\r\n        this._highlightedPoint = null;\r\n        \r\n        // set highlight colors if none provided\r\n        if (this.highlightColors.length == 0) {\r\n            for (var i=0; i<this.seriesColors.length; i++){\r\n                var rgba = $.jqplot.getColorComponents(this.seriesColors[i]);\r\n                var newrgb = [rgba[0], rgba[1], rgba[2]];\r\n                var sum = newrgb[0] + newrgb[1] + newrgb[2];\r\n                for (var j=0; j<3; j++) {\r\n                    // when darkening, lowest color component can be is 60.\r\n                    newrgb[j] = (sum > 570) ?  newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]);\r\n                    newrgb[j] = parseInt(newrgb[j], 10);\r\n                }\r\n                this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')');\r\n            }\r\n        }\r\n        \r\n        this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors);\r\n        \r\n        plot.postParseOptionsHooks.addOnce(postParseOptions);\r\n        plot.postInitHooks.addOnce(postInit);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp);\r\n        plot.eventListenerHooks.addOnce('jqplotClick', handleClick);\r\n        plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick);\r\n        plot.postDrawHooks.addOnce(postPlotDraw);\r\n    };\r\n    \r\n    $.jqplot.PieRenderer.prototype.setGridData = function(plot) {\r\n        // set gridData property.  This will hold angle in radians of each data point.\r\n        var stack = [];\r\n        var td = [];\r\n        var sa = this.startAngle/180*Math.PI;\r\n        var tot = 0;\r\n        // don't know if we have any valid data yet, so set plot to not draw.\r\n        this._drawData = false;\r\n        for (var i=0; i<this.data.length; i++){\r\n            if (this.data[i][1] != 0) {\r\n                // we have data, O.K. to draw.\r\n                this._drawData = true;\r\n                if (this.showSlice[i] === undefined) {\r\n                  this.showSlice[i] = true;\r\n                }\r\n            }\r\n            stack.push(this.data[i][1]);\r\n            td.push([this.data[i][0]]);\r\n            if (i>0) {\r\n                stack[i] += stack[i-1];\r\n            }\r\n            tot += this.data[i][1];\r\n        }\r\n        var fact = Math.PI*2/stack[stack.length - 1];\r\n        \r\n        for (var i=0; i<stack.length; i++) {\r\n            td[i][1] = stack[i] * fact;\r\n            td[i][2] = this.data[i][1]/tot;\r\n        }\r\n        this.gridData = td;\r\n    };\r\n    \r\n    $.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) {\r\n        var stack = [];\r\n        var td = [];\r\n        var tot = 0;\r\n        var sa = this.startAngle/180*Math.PI;\r\n        // don't know if we have any valid data yet, so set plot to not draw.\r\n        this._drawData = false;\r\n        for (var i=0; i<data.length; i++){\r\n            if (this.data[i][1] != 0) {\r\n                // we have data, O.K. to draw.\r\n                this._drawData = true;\r\n            }\r\n            stack.push(data[i][1]);\r\n            td.push([data[i][0]]);\r\n            if (i>0) {\r\n                stack[i] += stack[i-1];\r\n            }\r\n            tot += data[i][1];\r\n        }\r\n        var fact = Math.PI*2/stack[stack.length - 1];\r\n        \r\n        for (var i=0; i<stack.length; i++) {\r\n            td[i][1] = stack[i] * fact;\r\n            td[i][2] = data[i][1]/tot;\r\n        }\r\n        return td;\r\n    };\r\n\r\n    function calcRadiusAdjustment(ang) {\r\n        return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0);\r\n    }\r\n\r\n    function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) {\r\n        var rprime = 0;\r\n        var ang = ang2 - ang1;\r\n        var absang = Math.abs(ang);\r\n        var sm = sliceMargin;\r\n        if (fill == false) {\r\n            sm += lineWidth;\r\n        }\r\n\r\n        if (sm > 0 && absang > 0.01 && absang < 6.282) {\r\n            rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang);\r\n        }\r\n\r\n        return rprime;\r\n    }\r\n    \r\n    $.jqplot.PieRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) {\r\n        if (this._drawData) {\r\n            var r = this._radius;\r\n            var fill = this.fill;\r\n            var lineWidth = this.lineWidth;\r\n            var sm = this.sliceMargin;\r\n            if (this.fill == false) {\r\n                sm += this.lineWidth;\r\n            }\r\n            ctx.save();\r\n            ctx.translate(this._center[0], this._center[1]);\r\n            \r\n            var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);\r\n\r\n            var transx = rprime * Math.cos((ang1 + ang2) / 2.0);\r\n            var transy = rprime * Math.sin((ang1 + ang2) / 2.0);\r\n\r\n            if ((ang2 - ang1) <= Math.PI) {\r\n                r -= rprime;  \r\n            }\r\n            else {\r\n                r += rprime;\r\n            }\r\n\r\n            ctx.translate(transx, transy);\r\n            \r\n            if (isShadow) {\r\n                for (var i=0, l=this.shadowDepth; i<l; i++) {\r\n                    ctx.save();\r\n                    ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI));\r\n                    doDraw(r);\r\n                }\r\n                for (var i=0, l=this.shadowDepth; i<l; i++) {\r\n                    ctx.restore();\r\n                }\r\n            }\r\n    \r\n            else {\r\n                doDraw(r);\r\n            }\r\n            ctx.restore();\r\n        }\r\n    \r\n        function doDraw (rad) {\r\n            // Fix for IE and Chrome that can't seem to draw circles correctly.\r\n            // ang2 should always be <= 2 pi since that is the way the data is converted.\r\n            // 2Pi = 6.2831853, Pi = 3.1415927\r\n             if (ang2 > 6.282 + this.startAngle) {\r\n                ang2 = 6.282 + this.startAngle;\r\n                if (ang1 > ang2) {\r\n                    ang1 = 6.281 + this.startAngle;\r\n                }\r\n            }\r\n            // Fix for IE, where it can't seem to handle 0 degree angles.  Also avoids\r\n            // ugly line on unfilled pies.\r\n            if (ang1 >= ang2) {\r\n                return;\r\n            }            \r\n        \r\n            ctx.beginPath();  \r\n            ctx.fillStyle = color;\r\n            ctx.strokeStyle = color;\r\n            ctx.lineWidth = lineWidth;\r\n            ctx.arc(0, 0, rad, ang1, ang2, false);\r\n            ctx.lineTo(0,0);\r\n            ctx.closePath();\r\n        \r\n            if (fill) {\r\n                ctx.fill();\r\n            }\r\n            else {\r\n                ctx.stroke();\r\n            }\r\n        }\r\n    };\r\n    \r\n    // called with scope of series\r\n    $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) {\r\n        var i;\r\n        var opts = (options != undefined) ? options : {};\r\n        // offset and direction of offset due to legend placement\r\n        var offx = 0;\r\n        var offy = 0;\r\n        var trans = 1;\r\n        var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors);\r\n        var sliceColor;\r\n\r\n        if (options.legendInfo && options.legendInfo.placement == 'insideGrid') {\r\n            var li = options.legendInfo;\r\n            switch (li.location) {\r\n                case 'nw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'w':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'sw':\r\n                    offx = li.width + li.xoffset;\r\n                    break;\r\n                case 'ne':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'e':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'se':\r\n                    offx = li.width + li.xoffset;\r\n                    trans = -1;\r\n                    break;\r\n                case 'n':\r\n                    offy = li.height + li.yoffset;\r\n                    break;\r\n                case 's':\r\n                    offy = li.height + li.yoffset;\r\n                    trans = -1;\r\n                    break;\r\n                default:\r\n                    break;\r\n            }\r\n        }\r\n        \r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        \r\n        //see http://stackoverflow.com/questions/20221461/hidpi-retina-plot-drawing\r\n        var cw = parseInt(ctx.canvas.style.width);\r\n        var ch = parseInt(ctx.canvas.style.height);\r\n        //\r\n        \r\n        var w = cw - offx - 2 * this.padding;\r\n        var h = ch - offy - 2 * this.padding;\r\n        var mindim = Math.min(w,h);\r\n        var d = mindim;\r\n        \r\n        // Fixes issue #272.  Thanks hugwijst!\r\n        // reset slice angles array.\r\n        this._sliceAngles = [];\r\n\r\n        var sm = this.sliceMargin;\r\n        if (this.fill == false) {\r\n            sm += this.lineWidth;\r\n        }\r\n        \r\n        var rprime;\r\n        var maxrprime = 0;\r\n\r\n        var ang, ang1, ang2, shadowColor;\r\n        var sa = this.startAngle / 180 * Math.PI;\r\n\r\n        // have to pre-draw shadows, so loop throgh here and calculate some values also.\r\n        for (var i=0, l=gd.length; i<l; i++) {\r\n            ang1 = (i == 0) ? sa : gd[i-1][1] + sa;\r\n            ang2 = gd[i][1] + sa;\r\n\r\n            this._sliceAngles.push([ang1, ang2]);\r\n\r\n            rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth);\r\n\r\n            if (Math.abs(ang2-ang1) > Math.PI) {\r\n                maxrprime = Math.max(rprime, maxrprime);  \r\n            }\r\n        }\r\n\r\n        if (this.diameter != null && this.diameter > 0) {\r\n            this._diameter = this.diameter - 2*maxrprime;\r\n        }\r\n        else {\r\n            this._diameter = d - 2*maxrprime;\r\n        }\r\n\r\n        // Need to check for undersized pie.  This can happen if\r\n        // plot area too small and legend is too big.\r\n        if (this._diameter < 6) {\r\n            $.jqplot.log('Diameter of pie too small, not rendering.');\r\n            return;\r\n        }\r\n\r\n        var r = this._radius = this._diameter/2;\r\n\r\n        this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)];\r\n\r\n        if (this.shadow) {\r\n            for (var i=0, l=gd.length; i<l; i++) {\r\n                shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')';\r\n                this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], shadowColor, true);\r\n            }\r\n        }\r\n        \r\n        for (var i=0; i<gd.length; i++) {\r\n\r\n            sliceColor = colorGenerator.next();\r\n\r\n            if (this.showSlice[i]) {\r\n                this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], sliceColor, false);\r\n            \r\n                if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) {\r\n                    var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label;\r\n                \r\n                    if (this.dataLabels == 'label') {\r\n                        fstr = this.dataLabelFormatString || '%s';\r\n                        label = $.jqplot.sprintf(fstr, gd[i][0]);\r\n                    }\r\n                    else if (this.dataLabels == 'value') {\r\n                        fstr = this.dataLabelFormatString || '%d';\r\n                        label = $.jqplot.sprintf(fstr, this.data[i][1]);\r\n                    }\r\n                    else if (this.dataLabels == 'percent') {\r\n                        fstr = this.dataLabelFormatString || '%d%%';\r\n                        label = $.jqplot.sprintf(fstr, gd[i][2]*100);\r\n                    }\r\n                    else if (this.dataLabels.constructor == Array) {\r\n                        fstr = this.dataLabelFormatString || '%s';\r\n                        label = $.jqplot.sprintf(fstr, this.dataLabels[i]);\r\n                    }\r\n                \r\n                    var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge;\r\n                \r\n                    var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left;\r\n                    var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top;\r\n                \r\n                    var labelelem = $('<div class=\"jqplot-pie-series jqplot-data-label\" style=\"position:absolute;\">' + label + '</div>').insertBefore(plot.eventCanvas._elem);\r\n                    if (this.dataLabelCenterOn) {\r\n                        x -= labelelem.width()/2;\r\n                        y -= labelelem.height()/2;\r\n                    }\r\n                    else {\r\n                        x -= labelelem.width() * Math.sin(avgang/2);\r\n                        y -= labelelem.height()/2;\r\n                    }\r\n                    x = Math.round(x);\r\n                    y = Math.round(y);\r\n                    labelelem.css({left: x, top: y});\r\n                }\r\n            }\r\n        }            \r\n    };\r\n    \r\n    $.jqplot.PieAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer;\r\n        \r\n    \r\n    // There are no traditional axes on a pie chart.  We just need to provide\r\n    // dummy objects with properties so the plot will render.\r\n    // called with scope of axis object.\r\n    $.jqplot.PieAxisRenderer.prototype.init = function(options){\r\n        //\r\n        this.tickRenderer = $.jqplot.PieTickRenderer;\r\n        $.extend(true, this, options);\r\n        // I don't think I'm going to need _dataBounds here.\r\n        // have to go Axis scaling in a way to fit chart onto plot area\r\n        // and provide u2p and p2u functionality for mouse cursor, etc.\r\n        // for convienence set _dataBounds to 0 and 100 and\r\n        // set min/max to 0 and 100.\r\n        this._dataBounds = {min:0, max:100};\r\n        this.min = 0;\r\n        this.max = 100;\r\n        this.showTicks = false;\r\n        this.ticks = [];\r\n        this.showMark = false;\r\n        this.show = false; \r\n    };\r\n    \r\n    \r\n    \r\n    \r\n    $.jqplot.PieLegendRenderer = function(){\r\n        $.jqplot.TableLegendRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer();\r\n    $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer;\r\n    \r\n    /**\r\n     * Class: $.jqplot.PieLegendRenderer\r\n     * Legend Renderer specific to pie plots.  Set by default\r\n     * when user creates a pie plot.\r\n     */\r\n    $.jqplot.PieLegendRenderer.prototype.init = function(options) {\r\n        // Group: Properties\r\n        //\r\n        // prop: numberRows\r\n        // Maximum number of rows in the legend.  0 or null for unlimited.\r\n        this.numberRows = null;\r\n        // prop: numberColumns\r\n        // Maximum number of columns in the legend.  0 or null for unlimited.\r\n        this.numberColumns = null;\r\n        // prop: width\r\n        // Fixed with of legend.  0 or null for auto size\r\n        this.width = null;\r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    // called with context of legend\r\n    $.jqplot.PieLegendRenderer.prototype.draw = function() {\r\n        var legend = this;\r\n        if (this.show) {\r\n            var series = this._series;\r\n\r\n\r\n            this._elem = $(document.createElement('table'));\r\n            this._elem.addClass('jqplot-table-legend');\r\n\r\n            var ss = {position:'absolute'};\r\n            if (this.background) {\r\n                ss['background'] = this.background;\r\n            }\r\n            if (this.border) {\r\n                ss['border'] = this.border;\r\n            }\r\n            if (this.fontSize) {\r\n                ss['fontSize'] = this.fontSize;\r\n            }\r\n            if (this.fontFamily) {\r\n                ss['fontFamily'] = this.fontFamily;\r\n            }\r\n            if (this.textColor) {\r\n                ss['textColor'] = this.textColor;\r\n            }\r\n            if (this.marginTop != null) {\r\n                ss['marginTop'] = this.marginTop;\r\n            }\r\n            if (this.marginBottom != null) {\r\n                ss['marginBottom'] = this.marginBottom;\r\n            }\r\n            if (this.marginLeft != null) {\r\n                ss['marginLeft'] = this.marginLeft;\r\n            }\r\n            if (this.marginRight != null) {\r\n                ss['marginRight'] = this.marginRight;\r\n            }\r\n\r\n            this._elem.css(ss);\r\n\r\n            // Pie charts legends don't go by number of series, but by number of data points\r\n            // in the series.  Refactor things here for that.\r\n            \r\n            var pad = false, \r\n                reverse = false,\r\n                nr, \r\n                nc;\r\n            var s = series[0];\r\n            var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors);\r\n            \r\n            if (s.show) {\r\n                var pd = s.data;\r\n                if (this.numberRows) {\r\n                    nr = this.numberRows;\r\n                    if (!this.numberColumns){\r\n                        nc = Math.ceil(pd.length/nr);\r\n                    }\r\n                    else{\r\n                        nc = this.numberColumns;\r\n                    }\r\n                }\r\n                else if (this.numberColumns) {\r\n                    nc = this.numberColumns;\r\n                    nr = Math.ceil(pd.length/this.numberColumns);\r\n                }\r\n                else {\r\n                    nr = pd.length;\r\n                    nc = 1;\r\n                }\r\n                \r\n                var i, j;\r\n                var tr, td1, td2; \r\n                var lt, tt, rs, color;\r\n                var idx = 0; \r\n                var div0, div1;   \r\n                \r\n                for (i=0; i<nr; i++) {\r\n                    tr = $(document.createElement('tr'));\r\n                    tr.addClass('jqplot-table-legend');\r\n                    \r\n                    if (reverse){\r\n                        tr.prependTo(this._elem);\r\n                    }\r\n                    \r\n                    else{\r\n                        tr.appendTo(this._elem);\r\n                    }\r\n                    \r\n                    for (j=0; j<nc; j++) {\r\n                        if (idx < pd.length) {\r\n                            tt = '';\r\n                            if (this.labels[idx]) {\r\n                                lt = this.labels[idx];\r\n                            }\r\n                            else {\r\n                                if (typeof pd[idx][0] === 'object') {\r\n                                    lt = pd[idx][0][0].toString();\r\n                                    tt = pd[idx][0][1].toString();\r\n                                }\r\n                                else  {\r\n                                    lt = pd[idx][0].toString();\r\n                                }\r\n                            }\r\n                            //lt = this.labels[idx] || pd[idx][0].toString();\r\n                            color = colorGenerator.next();\r\n                            if (!reverse){\r\n                                if (i>0){\r\n                                    pad = true;\r\n                                }\r\n                                else{\r\n                                    pad = false;\r\n                                }\r\n                            }\r\n                            else{\r\n                                if (i == nr -1){\r\n                                    pad = false;\r\n                                }\r\n                                else{\r\n                                    pad = true;\r\n                                }\r\n                            }\r\n                            rs = (pad) ? this.rowSpacing : '0';\r\n\r\n\r\n\r\n                            td1 = $(document.createElement('td'));\r\n                            td1.addClass('jqplot-table-legend jqplot-table-legend-swatch');\r\n                            td1.css({textAlign: 'center', paddingTop: rs});\r\n\r\n                            div0 = $(document.createElement('div'));\r\n                            div0.addClass('jqplot-table-legend-swatch-outline');\r\n                            if (tt !== '') {\r\n                                div0.attr(\"title\", tt);\r\n                            }\r\n                            div1 = $(document.createElement('div'));\r\n                            div1.addClass('jqplot-table-legend-swatch');\r\n                            div1.css({backgroundColor: color, borderColor: color});\r\n                            td1.append(div0.append(div1));\r\n\r\n                            td2 = $(document.createElement('td'));\r\n                            td2.addClass('jqplot-table-legend jqplot-table-legend-label');\r\n                            td2.css('paddingTop', rs);\r\n\r\n                            if (this.escapeHtml){\r\n                                td2.text(lt);\r\n                            }\r\n                            else {\r\n                                td2.html('<a title=\"' + tt + '\">' + lt + \"</a>\");\r\n                            }\r\n                            if (reverse) {\r\n                                td2.prependTo(tr);\r\n                                td1.prependTo(tr);\r\n                            }\r\n                            else {\r\n                                td1.appendTo(tr);\r\n                                td2.appendTo(tr);\r\n                            }\r\n                            pad = true;\r\n                        }\r\n                        idx++;\r\n                    }   \r\n                }\r\n            }\r\n        }\r\n        return this._elem;                \r\n    };\r\n    \r\n    $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            plot.target.trigger('jqplotDataMouseOver', ins);\r\n            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                plot.target.trigger('jqplotDataHighlight', ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    };\r\n    \r\n    \r\n    // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]);\r\n    \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        options = options || {};\r\n        options.axesDefaults = options.axesDefaults || {};\r\n        options.legend = options.legend || {};\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        // only set these if there is a pie series\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer == $.jqplot.PieRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.PieAxisRenderer;\r\n            options.legend.renderer = options.legend.renderer || $.jqplot.PieLegendRenderer;\r\n            options.legend.preDraw = true;\r\n            options.seriesDefaults.pointLabels = {show: false};\r\n        }\r\n    }\r\n    \r\n    function postInit(target, data, options) {\r\n        for (var i=0; i<this.series.length; i++) {\r\n            if (this.series[i].renderer.constructor == $.jqplot.PieRenderer) {\r\n                // don't allow mouseover and mousedown at same time.\r\n                if (this.series[i].highlightMouseOver) {\r\n                    this.series[i].highlightMouseDown = false;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    \r\n    // called with scope of plot\r\n    function postParseOptions(options) {\r\n        for (var i=0; i<this.series.length; i++) {\r\n            this.series[i].seriesColors = this.seriesColors;\r\n            this.series[i].colorGenerator = $.jqplot.colorGenerator;\r\n        }\r\n    }\r\n    \r\n    function highlight (plot, sidx, pidx) {\r\n        if (plot.series[sidx].showSlice[pidx]) {\r\n            var s = plot.series[sidx];\r\n            var canvas = plot.plugins.pieRenderer.highlightCanvas;\r\n            canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n            s._highlightedPoint = pidx;\r\n            plot.plugins.pieRenderer.highlightedSeriesIndex = sidx;\r\n            s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColorGenerator.get(pidx), false);\r\n        }\r\n    }\r\n    \r\n    function unhighlight (plot) {\r\n        var canvas = plot.plugins.pieRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            plot.series[i]._highlightedPoint = null;\r\n        }\r\n        plot.plugins.pieRenderer.highlightedSeriesIndex = null;\r\n        plot.target.trigger('jqplotDataUnhighlight');\r\n    }\r\n \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt1 = jQuery.Event('jqplotDataMouseOver');\r\n            evt1.pageX = ev.pageX;\r\n            evt1.pageY = ev.pageY;\r\n            plot.target.trigger(evt1, ins);\r\n            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    } \r\n    \r\n    function handleMouseDown(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, ins[0], ins[1]);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n    \r\n    function handleMouseUp(ev, gridpos, datapos, neighbor, plot) {\r\n        var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;\r\n        if (idx != null && plot.series[idx].highlightMouseDown) {\r\n            unhighlight(plot);\r\n        }\r\n    }\r\n    \r\n    function handleClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt = jQuery.Event('jqplotDataClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }\r\n    \r\n    function handleRightClick(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var idx = plot.plugins.pieRenderer.highlightedSeriesIndex;\r\n            if (idx != null && plot.series[idx].highlightMouseDown) {\r\n                unhighlight(plot);\r\n            }\r\n            var evt = jQuery.Event('jqplotDataRightClick');\r\n            evt.which = ev.which;\r\n            evt.pageX = ev.pageX;\r\n            evt.pageY = ev.pageY;\r\n            plot.target.trigger(evt, ins);\r\n        }\r\n    }    \r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    function postPlotDraw() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.pieRenderer && this.plugins.pieRenderer.highlightCanvas) {\r\n            this.plugins.pieRenderer.highlightCanvas.resetCanvas();\r\n            this.plugins.pieRenderer.highlightCanvas = null;\r\n        }\r\n\r\n        this.plugins.pieRenderer = {highlightedSeriesIndex:null};\r\n        this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        \r\n        // do we have any data labels?  if so, put highlight canvas before those\r\n        var labels = $(this.targetId+' .jqplot-data-label');\r\n        if (labels.length) {\r\n            $(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));\r\n        }\r\n        // else put highlight canvas before event canvas.\r\n        else {\r\n            this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this));\r\n        }\r\n        \r\n        var hctx = this.plugins.pieRenderer.highlightCanvas.setContext();\r\n        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });\r\n    }\r\n    \r\n    $.jqplot.preInitHooks.push(preInit);\r\n    \r\n    $.jqplot.PieTickRenderer = function() {\r\n        $.jqplot.AxisTickRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer();\r\n    $.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer;\r\n    \r\n})(jQuery);\r\n    \r\n    "
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.pointLabels.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    \r\n    /**\r\n     * Class: $.jqplot.PointLabels\r\n     * Plugin for putting labels at the data points.\r\n     * \r\n     * To use this plugin, include the js\r\n     * file in your source:\r\n     * \r\n     * > <script type=\"text/javascript\" src=\"plugins/jqplot.pointLabels.js\"></script>\r\n     * \r\n     * By default, the last value in the data ponit array in the data series is used\r\n     * for the label.  For most series renderers, extra data can be added to the \r\n     * data point arrays and the last value will be used as the label.\r\n     * \r\n     * For instance, \r\n     * this series:\r\n     * \r\n     * > [[1,4], [3,5], [7,2]]\r\n     * \r\n     * Would, by default, use the y values in the labels.\r\n     * Extra data can be added to the series like so:\r\n     * \r\n     * > [[1,4,'mid'], [3 5,'hi'], [7,2,'low']]\r\n     * \r\n     * And now the point labels would be 'mid', 'low', and 'hi'.\r\n     * \r\n     * Options to the point labels and a custom labels array can be passed into the\r\n     * \"pointLabels\" option on the series option like so:\r\n     * \r\n     * > series:[{pointLabels:{\r\n     * >    labels:['mid', 'hi', 'low'],\r\n     * >    location:'se',\r\n     * >    ypadding: 12\r\n     * >    }\r\n     * > }]\r\n     * \r\n     * A custom labels array in the options takes precendence over any labels\r\n     * in the series data.  If you have a custom labels array in the options,\r\n     * but still want to use values from the series array as labels, set the\r\n     * \"labelsFromSeries\" option to true.\r\n     * \r\n     * By default, html entities (<, >, etc.) are escaped in point labels.  \r\n     * If you want to include actual html markup in the labels, \r\n     * set the \"escapeHTML\" option to false.\r\n     * \r\n     */\r\n    $.jqplot.PointLabels = function(options) {\r\n        // Group: Properties\r\n        //\r\n        // prop: show\r\n        // show the labels or not.\r\n        this.show = $.jqplot.config.enablePlugins;\r\n        // prop: location\r\n        // compass location where to position the label around the point.\r\n        // 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'\r\n        this.location = 'n';\r\n        // prop: labelsFromSeries\r\n        // true to use labels within data point arrays.\r\n        this.labelsFromSeries = false;\r\n        // prop: seriesLabelIndex\r\n        // array index for location of labels within data point arrays.\r\n        // if null, will use the last element of the data point array.\r\n        this.seriesLabelIndex = null;\r\n        // prop: labels\r\n        // array of arrays of labels, one array for each series.\r\n        this.labels = [];\r\n        // actual labels that will get displayed.\r\n        // needed to preserve user specified labels in labels array.\r\n        this._labels = [];\r\n        // prop: stackedValue\r\n        // true to display value as stacked in a stacked plot.\r\n        // no effect if labels is specified.\r\n        this.stackedValue = false;\r\n        // prop: ypadding\r\n        // vertical padding in pixels between point and label\r\n        this.ypadding = 6;\r\n        // prop: xpadding\r\n        // horizontal padding in pixels between point and label\r\n        this.xpadding = 6;\r\n        // prop: escapeHTML\r\n        // true to escape html entities in the labels.\r\n        // If you want to include markup in the labels, set to false.\r\n        this.escapeHTML = true;\r\n        // prop: edgeTolerance\r\n        // Number of pixels that the label must be away from an axis\r\n        // boundary in order to be drawn.  Negative values will allow overlap\r\n        // with the grid boundaries.\r\n        this.edgeTolerance = -5;\r\n        // prop: formatter\r\n        // A class of a formatter for the tick text.  sprintf by default.\r\n        this.formatter = $.jqplot.DefaultTickFormatter;\r\n        // prop: formatString\r\n        // string passed to the formatter.\r\n        this.formatString = '';\r\n        // prop: hideZeros\r\n        // true to not show a label for a value which is 0.\r\n        this.hideZeros = false;\r\n        this._elems = [];\r\n        \r\n        $.extend(true, this, options);\r\n    };\r\n    \r\n    var locations = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'];\r\n    var locationIndicies = {'nw':0, 'n':1, 'ne':2, 'e':3, 'se':4, 's':5, 'sw':6, 'w':7};\r\n    var oppositeLocations = ['se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e'];\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.PointLabels.init = function (target, data, seriesDefaults, opts, plot){\r\n        var options = $.extend(true, {}, seriesDefaults, opts);\r\n        options.pointLabels = options.pointLabels || {};\r\n        if (this.renderer.constructor === $.jqplot.BarRenderer && this.barDirection === 'horizontal' && !options.pointLabels.location) {\r\n            options.pointLabels.location = 'e';\r\n        }\r\n        // add a pointLabels attribute to the series plugins\r\n        this.plugins.pointLabels = new $.jqplot.PointLabels(options.pointLabels);\r\n        this.plugins.pointLabels.setLabels.call(this);\r\n    };\r\n    \r\n    // called with scope of series\r\n    $.jqplot.PointLabels.prototype.setLabels = function() {   \r\n        var p = this.plugins.pointLabels; \r\n        var labelIdx;\r\n        if (p.seriesLabelIndex != null) {\r\n            labelIdx = p.seriesLabelIndex;\r\n        }\r\n        else if (this.renderer.constructor === $.jqplot.BarRenderer && this.barDirection === 'horizontal') {\r\n           labelIdx = (this._plotData[0].length < 3) ? 0 : this._plotData[0].length -1;\r\n        }\r\n        else {\r\n            labelIdx = (this._plotData.length === 0) ? 0 : this._plotData[0].length -1;\r\n        }\r\n        p._labels = [];\r\n        if (p.labels.length === 0 || p.labelsFromSeries) {    \r\n            if (p.stackedValue) {\r\n                if (this._plotData.length && this._plotData[0].length){\r\n                    // var idx = p.seriesLabelIndex || this._plotData[0].length -1;\r\n                    for (var i=0; i<this._plotData.length; i++) {\r\n                        p._labels.push(this._plotData[i][labelIdx]);\r\n                    }\r\n                }\r\n            }\r\n            else {\r\n                // var d = this._plotData;\r\n                var d = this.data;\r\n                if (this.renderer.constructor === $.jqplot.BarRenderer && this.waterfall) {\r\n                    d = this._data;\r\n                }\r\n                if (d.length && d[0].length) {\r\n                    // var idx = p.seriesLabelIndex || d[0].length -1;\r\n                    for (var i=0; i<d.length; i++) {\r\n                        p._labels.push(d[i][labelIdx]);\r\n                    }\r\n                }\r\n                d = null;\r\n            }\r\n        }\r\n        else if (p.labels.length){\r\n            p._labels = p.labels;\r\n        }\r\n    };\r\n    \r\n    $.jqplot.PointLabels.prototype.xOffset = function(elem, location, padding) {\r\n        location = location || this.location;\r\n        padding = padding || this.xpadding;\r\n        var offset;\r\n        \r\n        switch (location) {\r\n            case 'nw':\r\n                offset = -elem.outerWidth(true) - this.xpadding;\r\n                break;\r\n            case 'n':\r\n                offset = -elem.outerWidth(true)/2;\r\n                break;\r\n            case 'ne':\r\n                offset =  this.xpadding;\r\n                break;\r\n            case 'e':\r\n                offset = this.xpadding;\r\n                break;\r\n            case 'se':\r\n                offset = this.xpadding;\r\n                break;\r\n            case 's':\r\n                offset = -elem.outerWidth(true)/2;\r\n                break;\r\n            case 'sw':\r\n                offset = -elem.outerWidth(true) - this.xpadding;\r\n                break;\r\n            case 'w':\r\n                offset = -elem.outerWidth(true) - this.xpadding;\r\n                break;\r\n            default: // same as 'nw'\r\n                offset = -elem.outerWidth(true) - this.xpadding;\r\n                break;\r\n        }\r\n        return offset; \r\n    };\r\n    \r\n    $.jqplot.PointLabels.prototype.yOffset = function(elem, location, padding) {\r\n        location = location || this.location;\r\n        padding = padding || this.xpadding;\r\n        var offset;\r\n        \r\n        switch (location) {\r\n            case 'nw':\r\n                offset = -elem.outerHeight(true) - this.ypadding;\r\n                break;\r\n            case 'n':\r\n                offset = -elem.outerHeight(true) - this.ypadding;\r\n                break;\r\n            case 'ne':\r\n                offset = -elem.outerHeight(true) - this.ypadding;\r\n                break;\r\n            case 'e':\r\n                offset = -elem.outerHeight(true)/2;\r\n                break;\r\n            case 'se':\r\n                offset = this.ypadding;\r\n                break;\r\n            case 's':\r\n                offset = this.ypadding;\r\n                break;\r\n            case 'sw':\r\n                offset = this.ypadding;\r\n                break;\r\n            case 'w':\r\n                offset = -elem.outerHeight(true)/2;\r\n                break;\r\n            default: // same as 'nw'\r\n                offset = -elem.outerHeight(true) - this.ypadding;\r\n                break;\r\n        }\r\n        return offset; \r\n    };\r\n    \r\n    // called with scope of series\r\n    $.jqplot.PointLabels.draw = function (sctx, options, plot) {\r\n        var p = this.plugins.pointLabels;\r\n        // set labels again in case they have changed.\r\n        p.setLabels.call(this);\r\n        // remove any previous labels\r\n        for (var i=0; i<p._elems.length; i++) {\r\n            // Memory Leaks patch\r\n            // p._elems[i].remove();\r\n            if(p._elems[i]) {\r\n                p._elems[i].emptyForce();\r\n            }\r\n        }\r\n        p._elems.splice(0, p._elems.length);\r\n\r\n        if (p.show) {\r\n            var ax = '_'+this._stackAxis+'axis';\r\n        \r\n            if (!p.formatString) {\r\n                p.formatString = this[ax]._ticks[0].formatString;\r\n                p.formatter = this[ax]._ticks[0].formatter;\r\n            }\r\n        \r\n            var pd = this._plotData;\r\n            var ppd = this._prevPlotData;\r\n            var xax = this._xaxis;\r\n            var yax = this._yaxis;\r\n            var elem, helem;\r\n\r\n            for (var i=0, l=p._labels.length; i < l; i++) {\r\n                var label = p._labels[i];\r\n                \r\n                if (label == null || (p.hideZeros && parseFloat(label) == 0)) {\r\n                    continue;\r\n                }\r\n                \r\n                label = p.formatter(p.formatString, label);\r\n\r\n                helem = document.createElement('div');\r\n                p._elems[i] = $(helem);\r\n\r\n                elem = p._elems[i];\r\n\r\n\r\n                elem.addClass('jqplot-point-label jqplot-series-'+this.index+' jqplot-point-'+i);\r\n                elem.css('position', 'absolute');\r\n                elem.insertAfter(sctx.canvas);\r\n\r\n                if (p.escapeHTML) {\r\n                    elem.text(label);\r\n                }\r\n                else {\r\n                    elem.html(label);\r\n                }\r\n                var location = p.location;\r\n                if ((this.fillToZero && pd[i][1] < 0) || (this.fillToZero && this._type === 'bar' && this.barDirection === 'horizontal' && pd[i][0] < 0) || (this.waterfall && parseInt(label, 10)) < 0) {\r\n                    location = oppositeLocations[locationIndicies[location]];\r\n                }\r\n\r\n\r\n                var ell = xax.u2p(pd[i][0]) + p.xOffset(elem, location);\r\n                var elt = yax.u2p(pd[i][1]) + p.yOffset(elem, location);\r\n\r\n                // we have stacked chart but are not showing stacked values,\r\n                // place labels in center.\r\n                if (this._stack && !p.stackedValue) {\r\n                    if (this.barDirection === \"vertical\") {\r\n                        elt = (this._barPoints[i][0][1] + this._barPoints[i][1][1]) / 2 + plot._gridPadding.top - 0.5 * elem.outerHeight(true);\r\n                    }\r\n                    else {\r\n                        ell = (this._barPoints[i][2][0] + this._barPoints[i][0][0]) / 2 + plot._gridPadding.left - 0.5 * elem.outerWidth(true);\r\n                    }\r\n                }\r\n\r\n                if (this.renderer.constructor == $.jqplot.BarRenderer) {\r\n                    if (this.barDirection == \"vertical\") {\r\n                        ell += this._barNudge;\r\n                    }\r\n                    else {\r\n                        elt -= this._barNudge;\r\n                    }\r\n                }\r\n                elem.css('left', ell);\r\n                elem.css('top', elt);\r\n                var elr = ell + elem.width();\r\n                var elb = elt + elem.height();\r\n                var et = p.edgeTolerance;\r\n                var scl = $(sctx.canvas).position().left;\r\n                var sct = $(sctx.canvas).position().top;\r\n                var scr = sctx.canvas.width + scl;\r\n                var scb = sctx.canvas.height + sct;\r\n                // if label is outside of allowed area, remove it\r\n                if (ell - et < scl || elt - et < sct || elr + et > scr || elb + et > scb) {\r\n                    elem.remove();\r\n                }\r\n\r\n                elem = null;\r\n                helem = null;\r\n            }\r\n\r\n            // finally, animate them if the series is animated\r\n            // if (this.renderer.animation && this.renderer.animation._supported && this.renderer.animation.show && plot._drawCount < 2) {\r\n            //     var sel = '.jqplot-point-label.jqplot-series-'+this.index;\r\n            //     $(sel).hide();\r\n            //     $(sel).fadeIn(1000);\r\n            // }\r\n\r\n        }\r\n    };\r\n    \r\n    $.jqplot.postSeriesInitHooks.push($.jqplot.PointLabels.init);\r\n    $.jqplot.postDrawSeriesHooks.push($.jqplot.PointLabels.draw);\r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.pyramidAxisRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    $.jqplot.PyramidAxisRenderer = function() {\r\n        $.jqplot.LinearAxisRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.PyramidAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();\r\n    $.jqplot.PyramidAxisRenderer.prototype.constructor = $.jqplot.PyramidAxisRenderer;\r\n        \r\n    // called with scope of axis\r\n    $.jqplot.PyramidAxisRenderer.prototype.init = function(options){\r\n        // Group: Properties\r\n        //\r\n        // prop: position\r\n        // Position of axis.  Values are: top, bottom , left, center, right.\r\n        // By default, x and x2 axes are bottom, y axis is center.\r\n        this.position = null;\r\n        // prop: drawBaseline\r\n        // True to draw the axis baseline.\r\n        this.drawBaseline = true;\r\n        // prop: baselineWidth\r\n        // width of the baseline in pixels.\r\n        this.baselineWidth = null;\r\n        // prop: baselineColor\r\n        // CSS color spec for the baseline.\r\n        this.baselineColor = null;\r\n        this.tickSpacingFactor = 25;\r\n        this._type = 'pyramid';\r\n        this._splitAxis = false;\r\n        this._splitLength = null;\r\n        this.category = false;\r\n        this._autoFormatString = '';\r\n        this._overrideFormatString = false;\r\n        \r\n        $.extend(true, this, options);\r\n        this.renderer.options = options;\r\n\r\n        this.resetDataBounds = this.renderer.resetDataBounds;\r\n        this.resetDataBounds();\r\n\r\n    };\r\n\r\n    $.jqplot.PyramidAxisRenderer.prototype.resetDataBounds = function() {\r\n        // Go through all the series attached to this axis and find\r\n        // the min/max bounds for this axis.\r\n        var db = this._dataBounds;\r\n        db.min = null;\r\n        db.max = null;\r\n        var temp;\r\n        for (var i=0; i<this._series.length; i++) {\r\n            var s = this._series[i];\r\n            var d = s._plotData;\r\n            \r\n            for (var j=0, l=d.length; j<l; j++) { \r\n                if (this.name.charAt(0) === 'x') {\r\n                    temp = d[j][1];\r\n                    if ((temp !== null && temp < db.min) || db.min === null) {\r\n                        db.min = temp;\r\n                    }\r\n                    if ((temp !== null && temp > db.max) || db.max === null) {\r\n                        db.max = temp;\r\n                    }\r\n                }              \r\n                else {\r\n                    temp = d[j][0];\r\n                    if ((temp !== null && temp < db.min) || db.min === null) {\r\n                        db.min = temp;\r\n                    }\r\n                    if ((temp !== null && temp > db.max) || db.max === null) {\r\n                        db.max = temp;\r\n                    }\r\n                }              \r\n            }\r\n        }\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.PyramidAxisRenderer.prototype.draw = function(ctx, plot) {\r\n        if (this.show) {\r\n            // populate the axis label and value properties.\r\n            // createTicks is a method on the renderer, but\r\n            // call it within the scope of the axis.\r\n            this.renderer.createTicks.call(this, plot);\r\n            // fill a div with axes labels in the right direction.\r\n            // Need to pregenerate each axis to get its bounds and\r\n            // position it and the labels correctly on the plot.\r\n            var dim=0;\r\n            var temp;\r\n            // Added for theming.\r\n            if (this._elem) {\r\n                // Memory Leaks patch\r\n                //this._elem.empty();\r\n                this._elem.emptyForce();\r\n                this._elem = null;\r\n            }\r\n            \r\n            this._elem = $(document.createElement('div'));\r\n            this._elem.addClass('jqplot-axis jqplot-'+this.name);\r\n            this._elem.css('position', 'absolute');\r\n\r\n            \r\n            if (this.name == 'xaxis' || this.name == 'x2axis') {\r\n                this._elem.width(this._plotDimensions.width);\r\n            }\r\n            else {\r\n                this._elem.height(this._plotDimensions.height);\r\n            }\r\n            \r\n            // create a _label object.\r\n            this.labelOptions.axis = this.name;\r\n            this._label = new this.labelRenderer(this.labelOptions);\r\n            if (this._label.show) {\r\n                var elem = this._label.draw(ctx, plot);\r\n                elem.appendTo(this._elem);\r\n                elem = null;\r\n            }\r\n    \r\n            var t = this._ticks;\r\n            var tick;\r\n            for (var i=0; i<t.length; i++) {\r\n                tick = t[i];\r\n                if (tick.show && tick.showLabel && (!tick.isMinorTick)) {\r\n                    this._elem.append(tick.draw(ctx, plot));\r\n                }\r\n            }\r\n            tick = null;\r\n            t = null;\r\n        }\r\n        return this._elem;\r\n    };   \r\n\r\n    // Note, primes can be found on http://primes.utm.edu/\r\n    var _primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];\r\n\r\n\r\n    var _primesHash = {};\r\n\r\n    for (var i =0, l = _primes.length; i < l; i++) {\r\n        _primesHash[_primes[i]] = _primes[i];\r\n    }\r\n\r\n    // called with scope of axis\r\n    $.jqplot.PyramidAxisRenderer.prototype.createTicks = function(plot) {\r\n        // we're are operating on an axis here\r\n        var userTicks = this.ticks;\r\n        // databounds were set on axis initialization.\r\n        var db = this._dataBounds;\r\n        var dim;\r\n        var interval;\r\n        var min;\r\n        var max;\r\n        var range;\r\n        var pos1;\r\n        var pos2;\r\n        var tt;\r\n        var i;\r\n        var l;\r\n        var s;\r\n        // get a copy of user's settings for min/max.\r\n        var userMin = this.min;\r\n        var userMax = this.max;\r\n        var ut;\r\n        var t;\r\n        var threshold;\r\n        var tdim;\r\n        var scalefact;\r\n        var ret;\r\n        var tumin;\r\n        var tumax;\r\n        var maxVisibleTicks;\r\n        var val;\r\n        var skip = null;\r\n        var temp;\r\n        \r\n        // if we already have ticks, use them.\r\n        // ticks must be in order of increasing value.\r\n\r\n        if (userTicks.length) {\r\n            // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed\r\n            for (i=0, l=userTicks.length; i<l; i++){\r\n                ut = userTicks[i];\r\n                t = new this.tickRenderer(this.tickOptions);\r\n                if ($.isArray(ut)) {\r\n                    t.value = ut[0];\r\n                    t.label = ut[1];\r\n                    t.setTick(ut[0], this.name);\r\n                    this._ticks.push(t);\r\n                }\r\n\r\n                else if ($.isPlainObject(ut)) {\r\n                    $.extend(true, t, ut);\r\n                    t.axis = this.name;\r\n                    this._ticks.push(t);\r\n                }\r\n                \r\n                else {\r\n                    if (typeof ut === 'string') {\r\n                        val = i + plot.defaultAxisStart;\r\n                    }\r\n                    else {\r\n                        val = ut;\r\n                    }\r\n                    t.value = val;\r\n                    t.label = ut;\r\n                    t.axis = this.name;\r\n                    this._ticks.push(t);\r\n                }\r\n            }\r\n            this.numberTicks = userTicks.length;\r\n            this.min = this._ticks[0].value;\r\n            this.max = this._ticks[this.numberTicks-1].value;\r\n            this.tickInterval = (this.max - this.min) / (this.numberTicks - 1);\r\n\r\n            // use user specified tickInterval if there is one\r\n            if (this._options.tickInterval) {\r\n                // hide every tick except for ticks on interval\r\n                var ti = this._options.tickInterval;\r\n                for (i=0; i<this.numberTicks; i++) {\r\n                    if (i%ti !== 0) {\r\n                        // this._ticks[i].show = false;\r\n                        this._ticks[i].isMinorTick = true;\r\n                    }\r\n                }\r\n            }\r\n\r\n            else {\r\n                // check if we have too many ticks\r\n                dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height;\r\n                maxVisibleTicks = Math.round(2.0 + dim/this.tickSpacingFactor);\r\n\r\n                if (this.numberTicks > maxVisibleTicks) {\r\n                    // check for number of ticks we can skip\r\n                    temp = this.numberTicks - 1;\r\n                    for (i=2; i<temp; i++) {\r\n                        if (temp % i === 0 && temp/i < maxVisibleTicks) {\r\n                            skip = i-1;\r\n                            break;\r\n                        }\r\n                    }\r\n\r\n                    if (skip !== null) {\r\n                        var count = 1;\r\n                        for (i=1, l=this._ticks.length; i<l; i++) {\r\n                            if (count <= skip) {\r\n                                this._ticks[i].show = false;\r\n                                count += 1;\r\n                            }\r\n                            else {\r\n                                count = 1;\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n            // if category style, add minor ticks in between\r\n            temp = [];\r\n            if (this.category) {\r\n                // turn off gridline and mark on first tick\r\n                this._ticks[0].showGridline = false;\r\n                this._ticks[0].showMark = false;\r\n\r\n                for (i=this._ticks.length-1; i>0; i--) {\r\n                    t = new this.tickRenderer(this.tickOptions);\r\n                    t.value = this._ticks[i-1].value + this.tickInterval/2.0;\r\n                    t.label = '';\r\n                    t.showLabel = false;\r\n                    t.axis = this.name;\r\n                    this._ticks[i].showGridline = false;\r\n                    this._ticks[i].showMark = false;\r\n                    this._ticks.splice(i, 0, t);\r\n                    // temp.push(t);\r\n                }\r\n\r\n                // merge in the new ticks\r\n                // for (i=1, l=temp.length; i<l; i++) {\r\n                //     this._ticks.splice(i, 0, temp[i]);\r\n                // }\r\n\r\n                // now add a tick at beginning and end\r\n                t = new this.tickRenderer(this.tickOptions);\r\n                t.value = this._ticks[0].value - this.tickInterval/2.0;\r\n                t.label = '';\r\n                t.showLabel = false;\r\n                t.axis = this.name;\r\n                this._ticks.unshift(t);\r\n\r\n                t = new this.tickRenderer(this.tickOptions);\r\n                t.value = this._ticks[this._ticks.length-1].value + this.tickInterval/2.0;\r\n                t.label = '';\r\n                t.showLabel = false;\r\n                t.axis = this.name;\r\n                this._ticks.push(t);\r\n\r\n                this.tickInterval = this.tickInterval / 2.0;\r\n                this.numberTicks = this._ticks.length;\r\n                this.min = this._ticks[0].value;\r\n                this.max = this._ticks[this._ticks.length-1].value;\r\n            }\r\n        }\r\n\r\n        // we don't have any ticks yet, let's make some!\r\n        else {\r\n            if (this.name.charAt(0) === 'x') {\r\n                dim = this._plotDimensions.width;\r\n                // make sure x axis is symetric about 0.\r\n                var tempmax = Math.max(db.max, Math.abs(db.min));\r\n                var tempmin = Math.min(db.min, -tempmax);\r\n                // min = ((this.min != null) ? this.min : tempmin);\r\n                // max = ((this.max != null) ? this.max : tempmax);\r\n                min = tempmin;\r\n                max = tempmax;\r\n                range = max - min;\r\n\r\n                if (this.tickOptions == null || !this.tickOptions.formatString) {\r\n                    this._overrideFormatString = true;\r\n                }\r\n\r\n                threshold = 30;\r\n                tdim = Math.max(dim, threshold+1);\r\n                scalefact =  (tdim-threshold)/300.0;\r\n                ret = $.jqplot.LinearTickGenerator(min, max, scalefact); \r\n                // calculate a padded max and min, points should be less than these\r\n                // so that they aren't too close to the edges of the plot.\r\n                // User can adjust how much padding is allowed with pad, padMin and PadMax options. \r\n                tumin = min + range*(this.padMin - 1);\r\n                tumax = max - range*(this.padMax - 1);\r\n\r\n                if (min < tumin || max > tumax) {\r\n                    tumin = min - range*(this.padMin - 1);\r\n                    tumax = max + range*(this.padMax - 1);\r\n                    ret = $.jqplot.LinearTickGenerator(tumin, tumax, scalefact);\r\n                }\r\n\r\n                this.min = ret[0];\r\n                this.max = ret[1];\r\n                this.numberTicks = ret[2];\r\n                this._autoFormatString = ret[3];\r\n                this.tickInterval = ret[4];\r\n            }\r\n            else {\r\n                dim = this._plotDimensions.height;\r\n\r\n                // ticks will be on whole integers like 1, 2, 3, ... or 1, 4, 7, ...\r\n                min = db.min;\r\n                max = db.max;\r\n                s = this._series[0];\r\n                this._ticks = [];\r\n\r\n                range = max - min;\r\n\r\n                // if range is a prime, will get only 2 ticks, expand range in that case.\r\n                if (_primesHash[range]) {\r\n                    range += 1;\r\n                    max += 1;\r\n                }\r\n\r\n                this.max = max;\r\n                this.min = min;\r\n                \r\n                maxVisibleTicks = Math.round(2.0 + dim/this.tickSpacingFactor);\r\n\r\n                if (range + 1 <= maxVisibleTicks) {\r\n                    this.numberTicks = range + 1;\r\n                    this.tickInterval = 1.0;\r\n                }\r\n\r\n                else {\r\n                    // figure out a round number of ticks to skip in every interval\r\n                    // range / ti + 1 = nt\r\n                    // ti = range / (nt - 1)\r\n                    for (var i=maxVisibleTicks; i>1; i--) {\r\n                        if (range/(i - 1) === Math.round(range/(i - 1))) {\r\n                            this.numberTicks = i;\r\n                            this.tickInterval = range/(i - 1);\r\n                            break;\r\n                        }\r\n                        \r\n                    }\r\n                }\r\n            }\r\n            \r\n            if (this._overrideFormatString && this._autoFormatString != '') {\r\n                this.tickOptions = this.tickOptions || {};\r\n                this.tickOptions.formatString = this._autoFormatString;\r\n            }\r\n\r\n            var labelval;\r\n            for (i=0; i<this.numberTicks; i++) {\r\n                this.tickOptions.axis = this.name;\r\n                labelval = this.min + this.tickInterval * i;\r\n                if (this.name.charAt(0) === 'x') {\r\n                    labelval = Math.abs(labelval);\r\n                }\r\n                // this.tickOptions.label = String (labelval);\r\n                this.tickOptions.value = this.min + this.tickInterval * i;\r\n                t = new this.tickRenderer(this.tickOptions);\r\n\r\n                t.label = t.prefix + t.formatter(t.formatString, labelval);\r\n\r\n                this._ticks.push(t);\r\n                // for x axis, if y axis is in middle, add a symetrical 0 tick\r\n                if (this.name.charAt(0) === 'x' && plot.axes.yMidAxis.show && this.tickOptions.value === 0) {\r\n                    this._splitAxis = true;\r\n                    this._splitLength = plot.axes.yMidAxis.getWidth();\r\n                    // t.value = -this.max/2000.0;\r\n                    t = new this.tickRenderer(this.tickOptions);\r\n                    this._ticks.push(t);\r\n                    t.value = this.max/2000.0;\r\n                }\r\n            }\r\n            t = null;\r\n        }\r\n    };\r\n    \r\n    // called with scope of axis\r\n    $.jqplot.PyramidAxisRenderer.prototype.set = function() { \r\n        var dim = 0;\r\n        var temp;\r\n        var w = 0;\r\n        var h = 0;\r\n        var i;\r\n        var t;\r\n        var tick;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        if (this.show) {\r\n            t = this._ticks;\r\n            l = t.length;\r\n            for (i=0; i<l; i++) {\r\n                tick = t[i];\r\n                if (!tick._breakTick && tick.show && tick.showLabel && !tick.isMinorTick) {\r\n                    if (this.name.charAt(0) === 'x') {\r\n                        temp = tick._elem.outerHeight(true);\r\n                    }\r\n                    else {\r\n                        temp = tick._elem.outerWidth(true);\r\n                    }\r\n                    if (temp > dim) {\r\n                        dim = temp;\r\n                    }\r\n                }\r\n            }\r\n\r\n            if (this.name === 'yMidAxis') {\r\n                for (i=0; i<l; i++) {\r\n                    tick = t[i];\r\n                    if (tick._elem) {\r\n                        temp = (dim - tick._elem.outerWidth(true))/2.0;\r\n                        tick._elem.css('left', temp);\r\n                    }\r\n                }\r\n            }\r\n            tick = null;\r\n            t = null;\r\n            \r\n            if (lshow) {\r\n                w = this._label._elem.outerWidth(true);\r\n                h = this._label._elem.outerHeight(true); \r\n            }\r\n            if (this.name === 'xaxis') {\r\n                dim = dim + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'});\r\n            }\r\n            else if (this.name === 'x2axis') {\r\n                dim = dim + h;\r\n                this._elem.css({'height':dim+'px', left:'0px', top:'0px'});\r\n            }\r\n            else if (this.name === 'yaxis') {\r\n                dim = dim + w;\r\n                this._elem.css({'width':dim+'px', left:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n            else if (this.name === 'yMidAxis') {\r\n                // don't include width of label at all in width of axis?\r\n                // dim = (dim > w) ? dim : w;\r\n                var temp = dim/2.0 - w/2.0;\r\n                this._elem.css({'width':dim+'px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css({width: w, left: temp, top: 0});\r\n                }\r\n            }\r\n            else {\r\n                dim = dim + w;\r\n                this._elem.css({'width':dim+'px', right:'0px', top:'0px'});\r\n                if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) {\r\n                    this._label._elem.css('width', w+'px');\r\n                }\r\n            }\r\n        }  \r\n    };\r\n    \r\n    $.jqplot.PyramidAxisRenderer.prototype.pack = function(pos, offsets) { \r\n        // Add defaults for repacking from resetTickValues function.\r\n        pos = pos || {};\r\n        offsets = offsets || this._offsets;\r\n        \r\n        var ticks = this._ticks;\r\n        var max = this.max;\r\n        var min = this.min;\r\n        var offmax = offsets.max;\r\n        var offmin = offsets.min;\r\n        var lshow = (this._label == null) ? false : this._label.show;\r\n        \r\n        for (var p in pos) {\r\n            this._elem.css(p, pos[p]);\r\n        }\r\n        \r\n        this._offsets = offsets;\r\n        // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left.\r\n        var pixellength = offmax - offmin;\r\n        var unitlength = max - min;\r\n        var sl = this._splitLength;\r\n        \r\n        // point to unit and unit to point conversions references to Plot DOM element top left corner.\r\n        if (this._splitAxis) {\r\n            pixellength -= this._splitLength;\r\n            \r\n            // don't know that this one is correct.\r\n            this.p2u = function(p){\r\n                return (p - offmin) * unitlength / pixellength + min;\r\n            };\r\n        \r\n            this.u2p = function(u){\r\n                if (u <= 0) {\r\n                    return (u - min) * pixellength / unitlength + offmin;\r\n                }\r\n                else {\r\n                    return (u - min) * pixellength / unitlength + offmin + sl;\r\n                }\r\n            };\r\n                \r\n            this.series_u2p = function(u){\r\n                if (u <= 0) {\r\n                    return (u - min) * pixellength / unitlength;\r\n                }\r\n                else {\r\n                    return (u - min) * pixellength / unitlength + sl;\r\n                }\r\n            };\r\n\r\n            // don't know that this one is correct.\r\n            this.series_p2u = function(p){\r\n                return p * unitlength / pixellength + min;\r\n            };\r\n        }\r\n        else {\r\n            this.p2u = function(p){\r\n                return (p - offmin) * unitlength / pixellength + min;\r\n            };\r\n        \r\n            this.u2p = function(u){\r\n                return (u - min) * pixellength / unitlength + offmin;\r\n            };\r\n                \r\n            if (this.name.charAt(0) === 'x'){\r\n                this.series_u2p = function(u){\r\n                    return (u - min) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + min;\r\n                };\r\n            }\r\n        \r\n            else {\r\n                this.series_u2p = function(u){\r\n                    return (u - max) * pixellength / unitlength;\r\n                };\r\n                this.series_p2u = function(p){\r\n                    return p * unitlength / pixellength + max;\r\n                };\r\n            }\r\n        }\r\n        \r\n        if (this.show) {\r\n            if (this.name.charAt(0) === 'x') {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel) {\r\n                        var shim;\r\n                        \r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'xaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    // position at start\r\n                                    else {\r\n                                        shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'end':\r\n                                    shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'start':\r\n                                    shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                case 'middle':\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getWidth()/2;\r\n                        }\r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('left', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                if (lshow) {\r\n                    var w = this._label._elem.outerWidth(true);\r\n                    this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px');\r\n                    if (this.name == 'xaxis') {\r\n                        this._label._elem.css('bottom', '0px');\r\n                    }\r\n                    else {\r\n                        this._label._elem.css('top', '0px');\r\n                    }\r\n                    this._label.pack();\r\n                }\r\n            }\r\n            else {\r\n                for (var i=0; i<ticks.length; i++) {\r\n                    var t = ticks[i];\r\n                    if (t.show && t.showLabel && !t.isMinorTick) {                        \r\n                        var shim;\r\n                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {\r\n                            // will need to adjust auto positioning based on which axis this is.\r\n                            var temp = (this.name == 'yaxis') ? 1 : -1;\r\n                            switch (t.labelPosition) {\r\n                                case 'auto':\r\n                                    // position at end\r\n                                case 'end':\r\n                                    if (temp * t.angle < 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'start':\r\n                                    if (t.angle > 0) {\r\n                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    else {\r\n                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;\r\n                                    }\r\n                                    break;\r\n                                case 'middle':\r\n                                    // if (t.angle > 0) {\r\n                                    //     shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    // else {\r\n                                    //     shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;\r\n                                    // }\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                                default:\r\n                                    shim = -t.getHeight()/2;\r\n                                    break;\r\n                            }\r\n                        }\r\n                        else {\r\n                            shim = -t.getHeight()/2;\r\n                        }\r\n                        \r\n                        var val = this.u2p(t.value) + shim + 'px';\r\n                        t._elem.css('top', val);\r\n                        t.pack();\r\n                    }\r\n                }\r\n                if (lshow) {\r\n                    var h = this._label._elem.outerHeight(true);\r\n                    if (this.name !== 'yMidAxis') {\r\n                        this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px');\r\n                    }\r\n                    if (this.name == 'yaxis') {\r\n                        this._label._elem.css('left', '0px');\r\n                    }\r\n                    else if (this.name !== 'yMidAxis') {\r\n                        this._label._elem.css('right', '0px');\r\n                    }   \r\n                    this._label.pack();\r\n                }\r\n            }\r\n        }\r\n\r\n        ticks = null;\r\n    };\r\n})(jQuery);\r\n"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.pyramidGridRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {     \r\n    // Class: $.jqplot.CanvasGridRenderer\r\n    // The default jqPlot grid renderer, creating a grid on a canvas element.\r\n    // The renderer has no additional options beyond the <Grid> class.\r\n    $.jqplot.PyramidGridRenderer = function(){\r\n        $.jqplot.CanvasGridRenderer.call(this);\r\n    };\r\n\r\n    $.jqplot.PyramidGridRenderer.prototype = new $.jqplot.CanvasGridRenderer();\r\n    $.jqplot.PyramidGridRenderer.prototype.constructor = $.jqplot.PyramidGridRenderer;\r\n    \r\n    // called with context of Grid object\r\n    $.jqplot.CanvasGridRenderer.prototype.init = function(options) {\r\n        this._ctx;\r\n        this.plotBands = {\r\n            show: false,\r\n            color: 'rgb(230, 219, 179)',\r\n            axis: 'y',\r\n            start: null,\r\n            interval: 10\r\n        };\r\n        $.extend(true, this, options);\r\n        // set the shadow renderer options\r\n        var sopts = {lineJoin:'miter', lineCap:'round', fill:false, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.shadowWidth, closePath:false, strokeStyle:this.shadowColor};\r\n        this.renderer.shadowRenderer.init(sopts);\r\n    };\r\n    \r\n    $.jqplot.PyramidGridRenderer.prototype.draw = function() {\r\n        this._ctx = this._elem.get(0).getContext(\"2d\");\r\n        var ctx = this._ctx;\r\n        var axes = this._axes;\r\n        var xp = axes.xaxis.u2p;\r\n        var yp = axes.yMidAxis.u2p;\r\n        var xnudge = axes.xaxis.max/1000.0;\r\n        var xp0 = xp(0);\r\n        var xpn = xp(xnudge);\r\n        var ax = ['xaxis', 'yaxis', 'x2axis', 'y2axis','yMidAxis'];\r\n        // Add the grid onto the grid canvas.  This is the bottom most layer.\r\n        ctx.save();\r\n        ctx.clearRect(0, 0, this._plotDimensions.width, this._plotDimensions.height);\r\n        ctx.fillStyle = this.backgroundColor || this.background;\r\n\r\n        ctx.fillRect(this._left, this._top, this._width, this._height);\r\n\r\n        if (this.plotBands.show) {\r\n            ctx.save();\r\n            var pb = this.plotBands;\r\n            ctx.fillStyle = pb.color;\r\n            var axis;\r\n            var x, y, w, h;\r\n            // find axis to work with\r\n            if (pb.axis.charAt(0) === 'x') {\r\n                if (axes.xaxis.show) {\r\n                    axis = axes.xaxis;\r\n                }\r\n            }\r\n            else if (pb.axis.charAt(0) === 'y') {\r\n                if (axes.yaxis.show) {\r\n                    axis = axes.yaxis;\r\n                }\r\n                else if (axes.y2axis.show) {\r\n                    axis = axes.y2axis;\r\n                }\r\n                else if (axes.yMidAxis.show) {\r\n                    axis = axes.yMidAxis;\r\n                }\r\n            }\r\n\r\n            if (axis !== undefined) {\r\n                // draw some rectangles\r\n                var start = pb.start;\r\n                if (start === null) {\r\n                    start = axis.min;\r\n                }\r\n                for (var i = start; i < axis.max; i += 2 * pb.interval) {\r\n                    if (axis.name.charAt(0) === 'y') {\r\n                        x = this._left;\r\n                        if ((i + pb.interval) < axis.max) {\r\n                            y = axis.series_u2p(i + pb.interval) + this._top;\r\n                        }\r\n                        else {\r\n                            y = axis.series_u2p(axis.max) + this._top;\r\n                        }\r\n                        w = this._right - this._left;\r\n                        h = axis.series_u2p(start) - axis.series_u2p(start + pb.interval);\r\n                        ctx.fillRect(x, y, w, h);\r\n                    }\r\n                    // else {\r\n                    //     y = 0;\r\n                    //     x = axis.series_u2p(i);\r\n                    //     h = this._height;\r\n                    //     w = axis.series_u2p(start + pb.interval) - axis.series_u2p(start);\r\n                    // }\r\n\r\n                }\r\n            }\r\n            ctx.restore();\r\n        }\r\n        \r\n        ctx.save();\r\n        ctx.lineJoin = 'miter';\r\n        ctx.lineCap = 'butt';\r\n        ctx.lineWidth = this.gridLineWidth;\r\n        ctx.strokeStyle = this.gridLineColor;\r\n        var b, e, s, m;\r\n        for (var i=5; i>0; i--) {\r\n            var name = ax[i-1];\r\n            var axis = axes[name];\r\n            var ticks = axis._ticks;\r\n            var numticks = ticks.length;\r\n            if (axis.show) {\r\n                if (axis.drawBaseline) {\r\n                    var bopts = {};\r\n                    if (axis.baselineWidth !== null) {\r\n                        bopts.lineWidth = axis.baselineWidth;\r\n                    }\r\n                    if (axis.baselineColor !== null) {\r\n                        bopts.strokeStyle = axis.baselineColor;\r\n                    }\r\n                    switch (name) {\r\n                        case 'xaxis':\r\n                            if (axes.yMidAxis.show) {\r\n                                drawLine (this._left, this._bottom, xp0, this._bottom, bopts);\r\n                                drawLine (xpn, this._bottom, this._right, this._bottom, bopts);\r\n                            }\r\n                            else {\r\n                                drawLine (this._left, this._bottom, this._right, this._bottom, bopts);\r\n                            }\r\n                            break;\r\n                        case 'yaxis':\r\n                            drawLine (this._left, this._bottom, this._left, this._top, bopts);\r\n                            break;\r\n                        case 'yMidAxis':               \r\n                            drawLine(xp0, this._bottom, xp0, this._top, bopts);\r\n                            drawLine(xpn, this._bottom, xpn, this._top, bopts);\r\n                            break;\r\n                        case 'x2axis':\r\n                            if (axes.yMidAxis.show) {\r\n                                drawLine (this._left, this._top, xp0, this._top, bopts);\r\n                                drawLine (xpn, this._top, this._right, this._top, bopts);\r\n                            }\r\n                            else {\r\n                                drawLine (this._left, this._bottom, this._right, this._bottom, bopts);\r\n                            }\r\n                            break;\r\n                        case 'y2axis':\r\n                            drawLine (this._right, this._bottom, this._right, this._top, bopts);\r\n                            break;\r\n\r\n                    }\r\n                }\r\n                for (var j=numticks; j>0; j--) {\r\n                    var t = ticks[j-1];\r\n                    if (t.show) {\r\n                        var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                        switch (name) {\r\n                            case 'xaxis':\r\n                                // draw the grid line if we should\r\n                                if (t.showGridline && this.drawGridlines && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    drawLine(pos, this._top, pos, this._bottom);\r\n                                }\r\n                                \r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._bottom;\r\n                                            e = this._bottom+s;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._bottom-s;\r\n                                            e = this._bottom;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._bottom-s;\r\n                                            e = this._bottom+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._bottom;\r\n                                            e = this._bottom+s;\r\n                                            break;\r\n                                    }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false});\r\n                                    }\r\n                                    // draw the line\r\n                                    drawLine(pos, b, pos, e);\r\n                                }\r\n                                break;\r\n                            case 'yaxis':\r\n                                // draw the grid line\r\n                                if (t.showGridline && this.drawGridlines && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    drawLine(this._right, pos, this._left, pos);\r\n                                }\r\n\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._left-s;\r\n                                            e = this._left;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._left;\r\n                                            e = this._left+s;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._left-s;\r\n                                            e = this._left+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._left-s;\r\n                                            e = this._left;\r\n                                            break;\r\n                                            }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor});\r\n                                }\r\n                                break;\r\n                            case 'yMidAxis':\r\n                                // draw the grid line\r\n                                if (t.showGridline && this.drawGridlines && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    drawLine(this._left, pos, xp0, pos);\r\n                                    drawLine(xpn, pos, this._right, pos);\r\n                                }\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n\r\n                                    b = xp0;\r\n                                    e = xp0 + s;\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor});\r\n\r\n                                    b = xpn - s;\r\n                                    e = xpn;\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor});\r\n                                }\r\n                                break;\r\n                            case 'x2axis':\r\n                                // draw the grid line\r\n                                if (t.showGridline && this.drawGridlines && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    drawLine(pos, this._bottom, pos, this._top);\r\n                                }\r\n\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._top-s;\r\n                                            e = this._top;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._top;\r\n                                            e = this._top+s;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._top-s;\r\n                                            e = this._top+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._top-s;\r\n                                            e = this._top;\r\n                                            break;\r\n                                            }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(pos, b, pos, e);\r\n                                }\r\n                                break;\r\n                            case 'y2axis':\r\n                                // draw the grid line\r\n                                if (t.showGridline && this.drawGridlines && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    drawLine(this._left, pos, this._right, pos);\r\n                                }\r\n\r\n                                // draw the mark\r\n                                if (t.showMark && t.mark && (!t.isMinorTick || axis.showMinorTicks)) {\r\n                                    s = t.markSize;\r\n                                    m = t.mark;\r\n                                    var pos = Math.round(axis.u2p(t.value)) + 0.5;\r\n                                    switch (m) {\r\n                                        case 'outside':\r\n                                            b = this._right;\r\n                                            e = this._right+s;\r\n                                            break;\r\n                                        case 'inside':\r\n                                            b = this._right-s;\r\n                                            e = this._right;\r\n                                            break;\r\n                                        case 'cross':\r\n                                            b = this._right-s;\r\n                                            e = this._right+s;\r\n                                            break;\r\n                                        default:\r\n                                            b = this._right;\r\n                                            e = this._right+s;\r\n                                            break;\r\n                                            }\r\n                                    // draw the shadow\r\n                                    if (this.shadow) {\r\n                                        this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false});\r\n                                    }\r\n                                    drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor});\r\n                                }\r\n                                break;\r\n                            default:\r\n                                break;\r\n                        }\r\n                    }\r\n                }\r\n                t = null;\r\n            }\r\n            axis = null;\r\n            ticks = null;\r\n        }\r\n        \r\n        ctx.restore();\r\n        \r\n        function drawLine(bx, by, ex, ey, opts) {\r\n            ctx.save();\r\n            opts = opts || {};\r\n            if (opts.lineWidth == null || opts.lineWidth != 0){\r\n                $.extend(true, ctx, opts);\r\n                ctx.beginPath();\r\n                ctx.moveTo(bx, by);\r\n                ctx.lineTo(ex, ey);\r\n                ctx.stroke();\r\n            }\r\n            ctx.restore();\r\n        }\r\n        \r\n        if (this.shadow) {\r\n            if (axes.yMidAxis.show) {\r\n                var points = [[this._left, this._bottom], [xp0, this._bottom]];\r\n                this.renderer.shadowRenderer.draw(ctx, points);\r\n                var points = [[xpn, this._bottom], [this._right, this._bottom], [this._right, this._top]];\r\n                this.renderer.shadowRenderer.draw(ctx, points);\r\n                var points = [[xp0, this._bottom], [xp0, this._top]];\r\n                this.renderer.shadowRenderer.draw(ctx, points);\r\n            }\r\n            else {\r\n                var points = [[this._left, this._bottom], [this._right, this._bottom], [this._right, this._top]];\r\n                this.renderer.shadowRenderer.draw(ctx, points);\r\n            }\r\n        }\r\n        // Now draw border around grid.  Use axis border definitions. start at\r\n        // upper left and go clockwise.\r\n        if (this.borderWidth != 0 && this.drawBorder) {\r\n            if (axes.yMidAxis.show) {\r\n                drawLine (this._left, this._top, xp0, this._top, {lineCap:'round', strokeStyle:axes.x2axis.borderColor, lineWidth:axes.x2axis.borderWidth});\r\n                drawLine (xpn, this._top, this._right, this._top, {lineCap:'round', strokeStyle:axes.x2axis.borderColor, lineWidth:axes.x2axis.borderWidth});\r\n                drawLine (this._right, this._top, this._right, this._bottom, {lineCap:'round', strokeStyle:axes.y2axis.borderColor, lineWidth:axes.y2axis.borderWidth});\r\n                drawLine (this._right, this._bottom, xpn, this._bottom, {lineCap:'round', strokeStyle:axes.xaxis.borderColor, lineWidth:axes.xaxis.borderWidth});\r\n                drawLine (xp0, this._bottom, this._left, this._bottom, {lineCap:'round', strokeStyle:axes.xaxis.borderColor, lineWidth:axes.xaxis.borderWidth});\r\n                drawLine (this._left, this._bottom, this._left, this._top, {lineCap:'round', strokeStyle:axes.yaxis.borderColor, lineWidth:axes.yaxis.borderWidth});\r\n                drawLine (xp0, this._bottom, xp0, this._top, {lineCap:'round', strokeStyle:axes.yaxis.borderColor, lineWidth:axes.yaxis.borderWidth});\r\n                drawLine (xpn, this._bottom, xpn, this._top, {lineCap:'round', strokeStyle:axes.yaxis.borderColor, lineWidth:axes.yaxis.borderWidth});\r\n            }\r\n            else {\r\n                drawLine (this._left, this._top, this._right, this._top, {lineCap:'round', strokeStyle:axes.x2axis.borderColor, lineWidth:axes.x2axis.borderWidth});\r\n                drawLine (this._right, this._top, this._right, this._bottom, {lineCap:'round', strokeStyle:axes.y2axis.borderColor, lineWidth:axes.y2axis.borderWidth});\r\n                drawLine (this._right, this._bottom, this._left, this._bottom, {lineCap:'round', strokeStyle:axes.xaxis.borderColor, lineWidth:axes.xaxis.borderWidth});\r\n                drawLine (this._left, this._bottom, this._left, this._top, {lineCap:'round', strokeStyle:axes.yaxis.borderColor, lineWidth:axes.yaxis.borderWidth});\r\n            }\r\n        }\r\n        // ctx.lineWidth = this.borderWidth;\r\n        // ctx.strokeStyle = this.borderColor;\r\n        // ctx.strokeRect(this._left, this._top, this._width, this._height);\r\n        \r\n        ctx.restore();\r\n        ctx =  null;\r\n        axes = null;\r\n    };\r\n})(jQuery); "
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.pyramidRenderer.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n\r\n    // Need to ensure pyramid axis and grid renderers are loaded.\r\n    // You should load these with script tags in the html head, that is more efficient\r\n    // as the browser will cache the request.\r\n    // Note, have to block with synchronous request in order to execute bar renderer code.\r\n    if ($.jqplot.PyramidAxisRenderer === undefined) {\r\n        $.ajax({\r\n            url: $.jqplot.pluginLocation + 'jqplot.pyramidAxisRenderer.js',\r\n            dataType: \"script\",\r\n            async: false\r\n        });\r\n    }\r\n    \r\n    if ($.jqplot.PyramidGridRenderer === undefined) {\r\n        $.ajax({\r\n            url: $.jqplot.pluginLocation + 'jqplot.pyramidGridRenderer.js',\r\n            dataType: \"script\",\r\n            async: false\r\n        });\r\n    }\r\n\r\n    $.jqplot.PyramidRenderer = function(){\r\n        $.jqplot.LineRenderer.call(this);\r\n    };\r\n    \r\n    $.jqplot.PyramidRenderer.prototype = new $.jqplot.LineRenderer();\r\n    $.jqplot.PyramidRenderer.prototype.constructor = $.jqplot.PyramidRenderer;\r\n    \r\n    // called with scope of a series\r\n    $.jqplot.PyramidRenderer.prototype.init = function(options, plot) {\r\n        options = options || {};\r\n        this._type = 'pyramid';\r\n        // Group: Properties\r\n        //\r\n        // prop: barPadding\r\n        this.barPadding = 10;\r\n        this.barWidth = null;\r\n        // prop: fill\r\n        // True to fill the bars.\r\n        this.fill = true;\r\n        // prop: highlightMouseOver\r\n        // True to highlight slice when moused over.\r\n        // This must be false to enable highlightMouseDown to highlight when clicking on a slice.\r\n        this.highlightMouseOver = true;\r\n        // prop: highlightMouseDown\r\n        // True to highlight when a mouse button is pressed over a slice.\r\n        // This will be disabled if highlightMouseOver is true.\r\n        this.highlightMouseDown = false;\r\n        // prop: highlightColors\r\n        // an array of colors to use when highlighting a slice.\r\n        this.highlightColors = [];\r\n        // prop highlightThreshold\r\n        // Expand the highlightable region in the x direction.\r\n        // E.g. a value of 3 will highlight a bar when the mouse is\r\n        // within 3 pixels of the bar in the x direction.\r\n        this.highlightThreshold = 2;\r\n        // prop: synchronizeHighlight\r\n        // Index of another series to highlight when this series is highlighted.\r\n        // null or false to not synchronize.\r\n        this.synchronizeHighlight = false;\r\n        // prop: offsetBars\r\n        // False will center bars on their y value.\r\n        // True will push bars up by 1/2 bar width to fill between their y values.\r\n        // If true, there needs to be 1 more tick than there are bars.\r\n        this.offsetBars = false;\r\n        \r\n        // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver\r\n        if (options.highlightMouseDown && options.highlightMouseOver == null) {\r\n            options.highlightMouseOver = false;\r\n        }\r\n\r\n        this.side = 'right';\r\n        \r\n        $.extend(true, this, options);\r\n\r\n        // if (this.fill === false) {\r\n        //     this.shadow = false;\r\n        // }\r\n\r\n        if (this.side === 'left') {\r\n            this._highlightThreshold = [[-this.highlightThreshold, 0], [-this.highlightThreshold, 0], [0,0], [0,0]];\r\n        }\r\n\r\n        else {\r\n            this._highlightThreshold = [[0,0], [0,0], [this.highlightThreshold, 0], [this.highlightThreshold, 0]];\r\n        }\r\n        \r\n        this.renderer.options = options;\r\n        // index of the currenty highlighted point, if any\r\n        this._highlightedPoint = null;\r\n        // Array of actual data colors used for each data point.\r\n        this._dataColors = [];\r\n        this._barPoints = [];\r\n        this.fillAxis = 'y';\r\n        this._primaryAxis = '_yaxis';\r\n        this._xnudge = 0;\r\n        \r\n        // set the shape renderer options\r\n        var opts = {lineJoin:'miter', lineCap:'butt', fill:this.fill, fillRect:this.fill, isarc:false, strokeStyle:this.color, fillStyle:this.color, closePath:this.fill, lineWidth: this.lineWidth};\r\n        this.renderer.shapeRenderer.init(opts);\r\n        // set the shadow renderer options\r\n        var shadow_offset = options.shadowOffset;\r\n        // set the shadow renderer options\r\n        if (shadow_offset == null) {\r\n            // scale the shadowOffset to the width of the line.\r\n            if (this.lineWidth > 2.5) {\r\n                shadow_offset = 1.25 * (1 + (Math.atan((this.lineWidth/2.5))/0.785398163 - 1)*0.6);\r\n                // var shadow_offset = this.shadowOffset;\r\n            }\r\n            // for skinny lines, don't make such a big shadow.\r\n            else {\r\n                shadow_offset = 1.25 * Math.atan((this.lineWidth/2.5))/0.785398163;\r\n            }\r\n        }\r\n        var sopts = {lineJoin:'miter', lineCap:'butt', fill:this.fill, fillRect:this.fill, isarc:false, angle:this.shadowAngle, offset:shadow_offset, alpha:this.shadowAlpha, depth:this.shadowDepth, closePath:this.fill, lineWidth: this.lineWidth};\r\n        this.renderer.shadowRenderer.init(sopts);\r\n\r\n        plot.postDrawHooks.addOnce(postPlotDraw);\r\n        plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove);\r\n\r\n        // if this is the left side of pyramid, set y values to negative.\r\n        if (this.side === 'left') {\r\n            for (var i=0, l=this.data.length; i<l; i++) {\r\n                this.data[i][1] = -Math.abs(this.data[i][1]);\r\n            }\r\n        }\r\n    };\r\n    \r\n    // setGridData\r\n    // converts the user data values to grid coordinates and stores them\r\n    // in the gridData array.\r\n    // Called with scope of a series.\r\n    $.jqplot.PyramidRenderer.prototype.setGridData = function(plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var data = this._plotData;\r\n        var pdata = this._prevPlotData;\r\n        this.gridData = [];\r\n        this._prevGridData = [];\r\n        var l = data.length;\r\n        var adjust = false;\r\n        var i;\r\n\r\n        // if any data values are < 0,  consider this a negative series\r\n        for (i = 0; i < l; i++) {\r\n            if (data[i][1] < 0) {\r\n                this.side = 'left';\r\n            }\r\n        }\r\n\r\n        if (this._yaxis.name === 'yMidAxis' && this.side === 'right') {\r\n            this._xnudge = this._xaxis.max/2000.0;\r\n            adjust = true;\r\n        }\r\n\r\n        for (i = 0; i < l; i++) {\r\n            // if not a line series or if no nulls in data, push the converted point onto the array.\r\n            if (data[i][0] != null && data[i][1] != null) {\r\n                this.gridData.push([xp(data[i][1]), yp(data[i][0])]);\r\n            }\r\n            // else if there is a null, preserve it.\r\n            else if (data[i][0] == null) {\r\n                this.gridData.push([xp(data[i][1]), null]);\r\n            }\r\n            else if (data[i][1] == null) {\r\n                this.gridData.push(null, [yp(data[i][0])]);\r\n            }\r\n            // finally, adjust x grid data if have to\r\n            if (data[i][1] === 0 && adjust) {\r\n                this.gridData[i][0] = xp(this._xnudge);\r\n            }\r\n        }\r\n    };\r\n    \r\n    // makeGridData\r\n    // converts any arbitrary data values to grid coordinates and\r\n    // returns them.  This method exists so that plugins can use a series'\r\n    // linerenderer to generate grid data points without overwriting the\r\n    // grid data associated with that series.\r\n    // Called with scope of a series.\r\n    $.jqplot.PyramidRenderer.prototype.makeGridData = function(data, plot) {\r\n        // recalculate the grid data\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var gd = [];\r\n        var l = data.length;\r\n        var adjust = false;\r\n        var i;\r\n\r\n        // if any data values are < 0,  consider this a negative series\r\n        for (i = 0; i < l; i++) {\r\n            if (data[i][1] < 0) {\r\n                this.side = 'left';\r\n            }\r\n        }\r\n\r\n        if (this._yaxis.name === 'yMidAxis' && this.side === 'right') {\r\n            this._xnudge = this._xaxis.max/2000.0;\r\n            adjust = true;\r\n        }\r\n\r\n        for (i = 0; i < l; i++) {\r\n            // if not a line series or if no nulls in data, push the converted point onto the array.\r\n            if (data[i][0] != null && data[i][1] != null) {\r\n                gd.push([xp(data[i][1]), yp(data[i][0])]);\r\n            }\r\n            // else if there is a null, preserve it.\r\n            else if (data[i][0] == null) {\r\n                gd.push([xp(data[i][1]), null]);\r\n            }\r\n            else if (data[i][1] == null) {\r\n                gd.push([null, yp(data[i][0])]);\r\n            }\r\n            // finally, adjust x grid data if have to\r\n            if (data[i][1] === 0 && adjust) {\r\n                gd[i][0] = xp(this._xnudge);\r\n            }\r\n        }\r\n\r\n        return gd;\r\n    };\r\n\r\n    $.jqplot.PyramidRenderer.prototype.setBarWidth = function() {\r\n        // need to know how many data values we have on the approprate axis and figure it out.\r\n        var i;\r\n        var nvals = 0;\r\n        var nseries = 0;\r\n        var paxis = this[this._primaryAxis];\r\n        var s, series, pos;\r\n        nvals = paxis.max - paxis.min;\r\n        var nticks = paxis.numberTicks;\r\n        var nbins = (nticks-1)/2;\r\n        // so, now we have total number of axis values.\r\n        var temp = (this.barPadding === 0) ? 1.0 : 0;\r\n        if (paxis.name == 'xaxis' || paxis.name == 'x2axis') {\r\n            this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals - this.barPadding + temp;\r\n        }\r\n        else {\r\n            if (this.fill) {\r\n                this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals - this.barPadding + temp;\r\n            }\r\n            else {\r\n                this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals;\r\n            }\r\n        }\r\n    };\r\n    \r\n    $.jqplot.PyramidRenderer.prototype.draw = function(ctx, gridData, options) {\r\n        var i;\r\n        // Ughhh, have to make a copy of options b/c it may be modified later.\r\n        var opts = $.extend({}, options);\r\n        var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow;\r\n        var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine;\r\n        var fill = (opts.fill != undefined) ? opts.fill : this.fill;\r\n        var xp = this._xaxis.series_u2p;\r\n        var yp = this._yaxis.series_u2p;\r\n        var pointx, pointy;\r\n        // clear out data colors.\r\n        this._dataColors = [];\r\n        this._barPoints = [];\r\n        \r\n        if (this.renderer.options.barWidth == null) {\r\n            this.renderer.setBarWidth.call(this);\r\n        }\r\n        \r\n        // var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this);\r\n        // var nvals = temp[0];\r\n        // var nseries = temp[1];\r\n        // var pos = temp[2];\r\n        var points = [],\r\n            w,\r\n            h;\r\n        \r\n        // this._barNudge = 0;\r\n\r\n        if (showLine) {\r\n            var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors);\r\n            var positiveColors = new $.jqplot.ColorGenerator(this.seriesColors);\r\n            var negativeColor = negativeColors.get(this.index);\r\n            if (! this.useNegativeColors) {\r\n                negativeColor = opts.fillStyle;\r\n            }\r\n            var positiveColor = opts.fillStyle;\r\n            var base;\r\n            var xstart = this._xaxis.series_u2p(this._xnudge);\r\n            var ystart = this._yaxis.series_u2p(this._yaxis.min);\r\n            var yend = this._yaxis.series_u2p(this._yaxis.max);\r\n            var bw = this.barWidth;\r\n            var bw2 = bw/2.0;\r\n            var points = [];\r\n            var yadj = this.offsetBars ? bw2 : 0;\r\n            \r\n            for (var i=0, l=gridData.length; i<l; i++) {\r\n                if (this.data[i][0] == null) {\r\n                    continue;\r\n                }\r\n                base = gridData[i][1];\r\n                // not stacked and first series in stack\r\n\r\n                if (this._plotData[i][1] < 0) {\r\n                    if (this.varyBarColor && !this._stack) {\r\n                        if (this.useNegativeColors) {\r\n                            opts.fillStyle = negativeColors.next();\r\n                        }\r\n                        else {\r\n                            opts.fillStyle = positiveColors.next();\r\n                        }\r\n                    }\r\n                }\r\n                else {\r\n                    if (this.varyBarColor && !this._stack) {\r\n                        opts.fillStyle = positiveColors.next();\r\n                    }\r\n                    else {\r\n                        opts.fillStyle = positiveColor;\r\n                    }                    \r\n                }\r\n                \r\n                if (this.fill) {\r\n\r\n                    if (this._plotData[i][1] >= 0) {\r\n                        // xstart = this._xaxis.series_u2p(this._xnudge);\r\n                        w = gridData[i][0] - xstart;\r\n                        h = this.barWidth;\r\n                        points = [xstart, base - bw2 - yadj, w, h];\r\n                    }\r\n                    else {\r\n                        // xstart = this._xaxis.series_u2p(0);\r\n                        w = xstart - gridData[i][0];\r\n                        h = this.barWidth;\r\n                        points = [gridData[i][0], base - bw2 - yadj, w, h];\r\n                    }\r\n\r\n                    this._barPoints.push([[points[0], points[1] + h], [points[0], points[1]], [points[0] + w, points[1]], [points[0] + w, points[1] + h]]);\r\n\r\n                    if (shadow) {\r\n                        this.renderer.shadowRenderer.draw(ctx, points);\r\n                    }\r\n                    var clr = opts.fillStyle || this.color;\r\n                    this._dataColors.push(clr);\r\n                    this.renderer.shapeRenderer.draw(ctx, points, opts); \r\n                }\r\n\r\n                else {\r\n                    if (i === 0) {\r\n                        points =[[xstart, ystart], [gridData[i][0], ystart], [gridData[i][0], gridData[i][1] - bw2 - yadj]];\r\n                    }\r\n\r\n                    else if (i < l-1) {\r\n                        points = points.concat([[gridData[i-1][0], gridData[i-1][1] - bw2 - yadj], [gridData[i][0], gridData[i][1] + bw2 - yadj], [gridData[i][0], gridData[i][1] - bw2 - yadj]]);\r\n                    } \r\n\r\n                    // finally, draw the line\r\n                    else {\r\n                        points = points.concat([[gridData[i-1][0], gridData[i-1][1] - bw2 - yadj], [gridData[i][0], gridData[i][1] + bw2 - yadj], [gridData[i][0], yend], [xstart, yend]]);\r\n                    \r\n                        if (shadow) {\r\n                            this.renderer.shadowRenderer.draw(ctx, points);\r\n                        }\r\n                        var clr = opts.fillStyle || this.color;\r\n                        this._dataColors.push(clr);\r\n                        this.renderer.shapeRenderer.draw(ctx, points, opts);\r\n                    }\r\n                }\r\n            }  \r\n        }        \r\n        \r\n        if (this.highlightColors.length == 0) {\r\n            this.highlightColors = $.jqplot.computeHighlightColors(this._dataColors);\r\n        }\r\n        \r\n        else if (typeof(this.highlightColors) == 'string') {\r\n            this.highlightColors = [];\r\n            for (var i=0; i<this._dataColors.length; i++) {\r\n                this.highlightColors.push(this.highlightColors);\r\n            }\r\n        }\r\n        \r\n    };\r\n\r\n        \r\n    // setup default renderers for axes and legend so user doesn't have to\r\n    // called with scope of plot\r\n    function preInit(target, data, options) {\r\n        options = options || {};\r\n        options.axesDefaults = options.axesDefaults || {};\r\n        options.grid = options.grid || {};\r\n        options.legend = options.legend || {};\r\n        options.seriesDefaults = options.seriesDefaults || {};\r\n        // only set these if there is a pie series\r\n        var setopts = false;\r\n        if (options.seriesDefaults.renderer === $.jqplot.PyramidRenderer) {\r\n            setopts = true;\r\n        }\r\n        else if (options.series) {\r\n            for (var i=0; i < options.series.length; i++) {\r\n                if (options.series[i].renderer === $.jqplot.PyramidRenderer) {\r\n                    setopts = true;\r\n                }\r\n            }\r\n        }\r\n        \r\n        if (setopts) {\r\n            options.axesDefaults.renderer = $.jqplot.PyramidAxisRenderer;\r\n            options.grid.renderer = $.jqplot.PyramidGridRenderer;\r\n            options.seriesDefaults.pointLabels = {show: false};\r\n        }\r\n    }\r\n    \r\n    // called within context of plot\r\n    // create a canvas which we can draw on.\r\n    // insert it before the eventCanvas, so eventCanvas will still capture events.\r\n    function postPlotDraw() {\r\n        // Memory Leaks patch    \r\n        if (this.plugins.pyramidRenderer && this.plugins.pyramidRenderer.highlightCanvas) {\r\n\r\n            this.plugins.pyramidRenderer.highlightCanvas.resetCanvas();\r\n            this.plugins.pyramidRenderer.highlightCanvas = null;\r\n        }\r\n         \r\n        this.plugins.pyramidRenderer = {highlightedSeriesIndex:null};\r\n        this.plugins.pyramidRenderer.highlightCanvas = new $.jqplot.GenericCanvas();\r\n        \r\n        this.eventCanvas._elem.before(this.plugins.pyramidRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pyramidRenderer-highlight-canvas', this._plotDimensions, this));\r\n        this.plugins.pyramidRenderer.highlightCanvas.setContext();\r\n        this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); });\r\n    }  \r\n    \r\n    function highlight (plot, sidx, pidx, points) {\r\n        var s = plot.series[sidx];\r\n        var canvas = plot.plugins.pyramidRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        s._highlightedPoint = pidx;\r\n        plot.plugins.pyramidRenderer.highlightedSeriesIndex = sidx;\r\n        var opts = {fillStyle: s.highlightColors[pidx], fillRect: false};\r\n        s.renderer.shapeRenderer.draw(canvas._ctx, points, opts);\r\n        if (s.synchronizeHighlight !== false && plot.series.length >= s.synchronizeHighlight && s.synchronizeHighlight !== sidx) {\r\n            s = plot.series[s.synchronizeHighlight];\r\n            opts = {fillStyle: s.highlightColors[pidx], fillRect: false};\r\n            s.renderer.shapeRenderer.draw(canvas._ctx, s._barPoints[pidx], opts);\r\n        }\r\n        canvas = null;\r\n    }\r\n    \r\n    function unhighlight (plot) {\r\n        var canvas = plot.plugins.pyramidRenderer.highlightCanvas;\r\n        canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height);\r\n        for (var i=0; i<plot.series.length; i++) {\r\n            plot.series[i]._highlightedPoint = null;\r\n        }\r\n        plot.plugins.pyramidRenderer.highlightedSeriesIndex = null;\r\n        plot.target.trigger('jqplotDataUnhighlight');\r\n        canvas =  null;\r\n    }\r\n    \r\n    \r\n    function handleMove(ev, gridpos, datapos, neighbor, plot) {\r\n        if (neighbor) {\r\n            var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data];\r\n            var evt1 = jQuery.Event('jqplotDataMouseOver');\r\n            evt1.pageX = ev.pageX;\r\n            evt1.pageY = ev.pageY;\r\n            plot.target.trigger(evt1, ins);\r\n            if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pyramidRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) {\r\n                var evt = jQuery.Event('jqplotDataHighlight');\r\n                evt.which = ev.which;\r\n                evt.pageX = ev.pageX;\r\n                evt.pageY = ev.pageY;\r\n                plot.target.trigger(evt, ins);\r\n                highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points);\r\n            }\r\n        }\r\n        else if (neighbor == null) {\r\n            unhighlight (plot);\r\n        }\r\n    }\r\n\r\n    // Have to add hook here, becuase it needs called before series is inited.\r\n    $.jqplot.preInitHooks.push(preInit);\r\n    \r\n\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/plugins/jqplot.trendline.js",
    "content": "/**\r\n * jqPlot\r\n * Pure JavaScript plotting plugin using jQuery\r\n *\r\n * Version: 1.0.9\r\n * Revision: d96a669\r\n *\r\n * Copyright (c) 2009-2016 Chris Leonello\r\n * jqPlot is currently available for use in all personal or commercial projects \r\n * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL \r\n * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can \r\n * choose the license that best suits your project and use it accordingly. \r\n *\r\n * Although not required, the author would appreciate an email letting him \r\n * know of any substantial use of jqPlot.  You can reach the author at: \r\n * chris at jqplot dot com or see http://www.jqplot.com/info.php .\r\n *\r\n * If you are feeling kind and generous, consider supporting the project by\r\n * making a donation at: http://www.jqplot.com/donate.php .\r\n *\r\n * sprintf functions contained in jqplot.sprintf.js by Ash Searle:\r\n *\r\n *     version 2007.04.27\r\n *     author Ash Searle\r\n *     http://hexmen.com/blog/2007/03/printf-sprintf/\r\n *     http://hexmen.com/js/sprintf.js\r\n *     The author (Ash Searle) has placed this code in the public domain:\r\n *     \"This code is unrestricted: you are free to use it however you like.\"\r\n * \r\n */\r\n(function($) {\r\n    \r\n    /**\r\n     * Class: $.jqplot.Trendline\r\n     * Plugin which will automatically compute and draw trendlines for plotted data.\r\n     */\r\n    $.jqplot.Trendline = function() {\r\n        // Group: Properties\r\n        \r\n        // prop: show\r\n        // Wether or not to show the trend line.\r\n        this.show = $.jqplot.config.enablePlugins;\r\n        // prop: color\r\n        // CSS color spec for the trend line.\r\n        // By default this wil be the same color as the primary line.\r\n        this.color = '#666666';\r\n        // prop: renderer\r\n        // Renderer to use to draw the trend line.\r\n        // The data series that is plotted may not be rendered as a line.\r\n        // Therefore, we use our own line renderer here to draw a trend line.\r\n        this.renderer = new $.jqplot.LineRenderer();\r\n        // prop: rendererOptions\r\n        // Options to pass to the line renderer.\r\n        // By default, markers are not shown on trend lines.\r\n        this.rendererOptions = {marker:{show:false}};\r\n        // prop: label\r\n        // Label for the trend line to use in the legend.\r\n        this.label = '';\r\n        // prop: type\r\n        // Either 'exponential', 'exp', or 'linear'.\r\n        this.type = 'linear';\r\n        // prop: shadow\r\n        // true or false, whether or not to show the shadow.\r\n        this.shadow = true;\r\n        // prop: markerRenderer\r\n        // Renderer to use to draw markers on the line.\r\n        // I think this is wrong.\r\n        this.markerRenderer = {show:false};\r\n        // prop: lineWidth\r\n        // Width of the trend line.\r\n        this.lineWidth = 1.5;\r\n        // prop: shadowAngle\r\n        // Angle of the shadow on the trend line.\r\n        this.shadowAngle = 45;\r\n        // prop: shadowOffset\r\n        // pixel offset for each stroke of the shadow.\r\n        this.shadowOffset = 1.0;\r\n        // prop: shadowAlpha\r\n        // Alpha transparency of the shadow.\r\n        this.shadowAlpha = 0.07;\r\n        // prop: shadowDepth\r\n        // number of strokes to make of the shadow.\r\n        this.shadowDepth = 3;\r\n        this.isTrendline = true;\r\n        \r\n    };\r\n    \r\n    $.jqplot.postSeriesInitHooks.push(parseTrendLineOptions);\r\n    $.jqplot.postDrawSeriesHooks.push(drawTrendline);\r\n    $.jqplot.addLegendRowHooks.push(addTrendlineLegend);\r\n    \r\n    // called witin scope of the legend object\r\n    // current series passed in\r\n    // must return null or an object {label:label, color:color}\r\n    function addTrendlineLegend(series) {\r\n        var ret = null;\r\n        if (series.trendline && series.trendline.show) {\r\n            var lt = series.trendline.label.toString();\r\n            if (lt) {\r\n                ret = {label:lt, color:series.trendline.color};\r\n            }\r\n        }\r\n        return ret;\r\n    }\r\n\r\n    // called within scope of a series\r\n    function parseTrendLineOptions (target, data, seriesDefaults, options, plot) {\r\n        if (this._type && (this._type === 'line' || this._type == 'bar')) {\r\n            this.trendline = new $.jqplot.Trendline();\r\n            options = options || {};\r\n            $.extend(true, this.trendline, {color:this.color}, seriesDefaults.trendline, options.trendline);\r\n            this.trendline.renderer.init.call(this.trendline, null);\r\n        }\r\n    }\r\n    \r\n    // called within scope of series object\r\n    function drawTrendline(sctx, options) {\r\n        // if we have options, merge trendline options in with precedence\r\n        options = $.extend(true, {}, this.trendline, options);\r\n\r\n        if (this.trendline && options.show) {\r\n            var fit;\r\n            // this.renderer.setGridData.call(this);\r\n            var data = options.data || this.data;\r\n            fit = fitData(data, this.trendline.type);\r\n            var gridData = options.gridData || this.renderer.makeGridData.call(this, fit.data);\r\n            this.trendline.renderer.draw.call(this.trendline, sctx, gridData, {showLine:true, shadow:this.trendline.shadow});\r\n        }\r\n    }\r\n    \r\n    function regression(x, y, typ)  {\r\n        var type = (typ == null) ? 'linear' : typ;\r\n        var N = x.length;\r\n        var slope;\r\n        var intercept;  \r\n        var SX = 0;\r\n        var SY = 0;\r\n        var SXX = 0;\r\n        var SXY = 0;\r\n        var SYY = 0;\r\n        var Y = [];\r\n        var X = [];\r\n    \r\n        if (type == 'linear') {\r\n            X = x;\r\n            Y = y;\r\n        }\r\n        else if (type == 'exp' || type == 'exponential') {\r\n            for ( var i=0; i<y.length; i++) {\r\n                // ignore points <= 0, log undefined.\r\n                if (y[i] <= 0) {\r\n                    N--;\r\n                }\r\n                else {\r\n                    X.push(x[i]);\r\n                    Y.push(Math.log(y[i]));\r\n                }\r\n            }\r\n        }\r\n\r\n        for ( var i = 0; i < N; i++) {\r\n            SX = SX + X[i];\r\n            SY = SY + Y[i];\r\n            SXY = SXY + X[i]* Y[i];\r\n            SXX = SXX + X[i]* X[i];\r\n            SYY = SYY + Y[i]* Y[i];\r\n        }\r\n\r\n        slope = (N*SXY - SX*SY)/(N*SXX - SX*SX);\r\n        intercept = (SY - slope*SX)/N;\r\n\r\n        return [slope, intercept];\r\n    }\r\n\r\n    function linearRegression(X,Y) {\r\n        var ret;\r\n        ret = regression(X,Y,'linear');\r\n        return [ret[0],ret[1]];\r\n    }\r\n\r\n    function expRegression(X,Y) {\r\n        var ret;\r\n        var x = X;\r\n        var y = Y;\r\n        ret = regression(x, y,'exp');\r\n        var base = Math.exp(ret[0]);\r\n        var coeff = Math.exp(ret[1]);\r\n        return [base, coeff];\r\n    }\r\n\r\n    function fitData(data, typ) {\r\n        var type = (typ == null) ?  'linear' : typ;\r\n        var ret;\r\n        var res;\r\n        var x = [];\r\n        var y = [];\r\n        var ypred = [];\r\n        \r\n        for (i=0; i<data.length; i++){\r\n            if (data[i] != null && data[i][0] != null && data[i][1] != null) {\r\n                x.push(data[i][0]);\r\n                y.push(data[i][1]);\r\n            }\r\n        }\r\n        \r\n        if (type == 'linear') {\r\n            ret = linearRegression(x,y);\r\n            for ( var i=0; i<x.length; i++){\r\n                res = ret[0]*x[i] + ret[1];\r\n                ypred.push([x[i], res]);\r\n            }\r\n        }\r\n        else if (type == 'exp' || type == 'exponential') {\r\n            ret = expRegression(x,y);\r\n            for ( var i=0; i<x.length; i++){\r\n                res = ret[1]*Math.pow(ret[0],x[i]);\r\n                ypred.push([x[i], res]);\r\n            }\r\n        }\r\n        return {data: ypred, slope: ret[0], intercept: ret[1]};\r\n    } \r\n\r\n})(jQuery);"
  },
  {
    "path": "pwnagotchi/ui/web/static/js/viewportHeight.js",
    "content": "/* https://css-tricks.com/the-trick-to-viewport-units-on-mobile/*/\n\nvar lastViewportHeight;\n\nfunction updateViewportSize() {\n  // First we get the viewport height and we multiple it by 1% to get a value for a vh unit\n  var vh = window.innerHeight * 0.01;\n  if (!lastViewportHeight || lastViewportHeight !== vh) {\n    // Then we set the value in the --vh custom property to the root of the document\n    document.documentElement.style.setProperty(\"--vh\", vh + \"px\");\n    lastViewportHeight = vh;\n  }\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n  updateViewportSize();\n});"
  },
  {
    "path": "pwnagotchi/ui/web/templates/base.html",
    "content": "<!DOCTYPE html>\n<html>\n{% block head %}\n<head>\n    {% block meta %}\n    <meta charset=\"utf-8\">\n    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    {% endblock %}\n\n    <title>\n        {% block title %}\n        {% endblock %}\n    </title>\n\n    {% block styles %}\n    <link rel=\"stylesheet\" href=\"/js/jquery.mobile/jquery.mobile-1.4.5.min.css\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/style.css\"/>\n    <link rel=\"apple-touch-icon\" href=\"/images/pwnagotchi.png\">\n    <link rel=\"icon\" type=\"image/png\" href=\"/images/pwnagotchi.png\">    \n    {% endblock %}\n\n</head>\n{% endblock %}\n\n{% block body %}\n<body>\n<div data-role=\"page\">\n\n    {% if error %}\n    <div id=\"error\" class=\"error ui-content\" data-role=\"popup\" data-overlay-theme=\"a\" data-theme=\"b\">\n        <p>{{ error }}</p>\n    </div>\n    <script>\n        $(function(){\n            $(\"#error\").popup(\"open\");\n        });\n    </script>\n    {% endif %}\n\n    {% set navigation = [\n        ( '/', 'home', 'eye', 'Home' ),\n        ( '/inbox', 'inbox', 'bars', 'Inbox' ),\n        ( '/inbox/new', 'new', 'mail', 'New' ),\n        ( '/inbox/profile', 'profile', 'info', 'Profile' ),\n        ( '/inbox/peers', 'peers', 'user', 'Peers' ),\n        ( '/plugins', 'plugins', 'grid', 'Plugins' ),\n    ] %}\n    {% set active_page = active_page|default('inbox') %}\n\n    <div data-role=\"footer\">\n        <div data-role=\"navbar\" data-iconpos=\"left\">\n            <ul>\n                {% for href, id, icon, caption in navigation %}\n                    <li class=\"navitem\">\n                       <a href=\"{{ href }}\" id=\"{{ id }}\" data-icon=\"{{ icon }}\" class=\"{{ 'ui-btn-active' if active_page == id }}\">{{ caption }}</a>\n                    </li>\n                {% endfor %}\n            </ul>\n        </div>\n    </div>\n\n    {% block content %}\n    {% endblock %}\n\n</div>\n{% block scripts %}\n<script type=\"text/javascript\" src=\"/js/jquery-1.12.4.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jquery.mobile/jquery.mobile-1.4.5.min.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jquery.timeago.js\"></script>\n<script type=\"text/javascript\" src=\"/js/jquery-qrcode-0.17.0.min.js\"></script>\n<script type=\"text/javascript\">\n    $.mobile.ajaxEnabled = false;\n    $.mobile.pushStateEnabled = false;\n\n    jQuery(document).ready(function() {\n      jQuery(\"time.timeago\").timeago();\n    });\n\n    {% block script %}\n    {% endblock %}\n</script>\n{% endblock %}\n</body>\n{% endblock %}\n</html>\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/inbox.html",
    "content": "{% extends \"base.html\" %}\n{% set active_page = \"inbox\" %}\n\n{% block title %}\n{{ name }} Inbox\n{% endblock %}\n\n{% block script %}\n$(function() {\n    setTimeout(function(){\n        window.location.reload(true);\n    }, 15000);\n});\n{% endblock %}\n\n{% block content %}\n<ul class=\"inbox\" data-role=\"listview\" data-filter=\"true\" data-filter-placeholder=\"Search inbox...\" data-inset=\"true\">\n    {% for message in inbox.messages %}\n    <li class=\"message\">\n        <a href=\"/inbox/{{ message.id }}\" class=\"{{ 'unread' if not message.seen_at else 'read' }}\">\n            <h2>{{ message.sender_name }}@{{ message.sender }}</h2>\n            <p>\n                Received\n                <time class=\"timeago\" datetime=\"{{ message.created_at }}\">{{ message.created_at }}</time>\n                {% if message.seen_at %}, seen\n                <time class=\"timeago\" datetime=\"{{ message.seen_at }}\">{{ message.seen_at }}</time>\n                {% endif %}.\n            </p>\n        </a>\n    </li>\n    {% endfor %}\n</ul>\n\n{% if inbox.pages > 1 %}\n<div data-role=\"navbar\">\n    <ul>\n        {% if page > 1 %}\n        <li><a href=\"/inbox?p={{ page - 1 }}\" class=\"ui-btn\">Prev</a></li>\n        {% endif %}\n        {% if page < inbox.pages %}\n        <li><a href=\"/inbox?p={{ page + 1 }}\" class=\"ui-btn\">Next</a></li>\n        {% endif %}\n    </ul>\n</div>\n{% endif %}\n{% endblock %}\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/index.html",
    "content": "{% extends \"base.html\" %}\n{% set active_page = \"home\" %}\n\n{% block title %}\n{{ title }}\n{% endblock %}\n\n{% block script %}\nwindow.onload = function() {\n    var image = document.getElementById(\"ui\");\n    function updateImage() {\n        image.src = image.src.split(\"?\")[0] + \"?\" + new Date().getTime();\n    }\n    setInterval(updateImage, 1000);\n}\n{% endblock %}\n\n{% block content %}\n<img class=\"ui-image pixelated\" src=\"/ui\" id=\"ui\"/>\n<div data-role=\"navbar\">\n\t<ul>\n\t\t<li>\n\t\t\t<form class=\"action\" method=\"post\" action=\"/shutdown\"\n          onsubmit=\"return confirm('this will halt the unit, continue?');\">\n\t\t\t\t<input type=\"submit\" class=\"button ui-btn ui-corner-all\" value=\"Shutdown\"/>\n\t\t\t\t<input type=\"hidden\" name=\"csrf_token\" value=\"{{ csrf_token() }}\"/>\n\t\t\t</form>\n\t\t</li>\n\t\t<li>\n\t\t\t<form class=\"action\" method=\"post\" action=\"/reboot\"\n          onsubmit=\"return confirm('this will reboot the unit, continue?');\">\n\t\t\t\t<input type=\"submit\" class=\"button ui-btn ui-corner-all\" value=\"Reboot\"/>\n\t\t\t\t<input type=\"hidden\" name=\"csrf_token\" value=\"{{ csrf_token() }}\"/>\n\t\t\t</form>\n\t\t</li>\n\t\t<li>\n\t\t\t<form class=\"action\" method=\"post\" action=\"/restart\"\n          onsubmit=\"return confirm('This will restart the service in {{ other_mode }} mode, continue?');\">\n\t\t\t\t<input type=\"submit\" class=\"button ui-btn ui-corner-all\" value=\"Restart in {{ other_mode }} mode\"/>\n\t\t\t\t<input type=\"hidden\" name=\"mode\" value=\"{{ other_mode }}\"/>\n\t\t\t\t<input type=\"hidden\" name=\"csrf_token\" value=\"{{ csrf_token() }}\"/>\n\t\t\t</form>\n\t\t</li>\n\t</ul>\n</div>\n{% endblock %}\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/message.html",
    "content": "{% extends \"base.html\" %}\n{% set active_page = \"\" %}\n\n{% block title %}\nMessage from {{ message.sender_name }}\n{% endblock %}\n\n{% block script %}\njQuery(document).ready(function() {\n    // mark the message as read\n    jQuery.get(\"/inbox/{{ message.id }}/seen\", function(res){ console.log(res); });\n});\n{% endblock %}\n\n{% block content %}\n<p class=\"messagebody\">\n        <span style=\"color: #888\">\n        Message from {{ message.sender_name }}@{{ message.sender }}, sent\n        <time class=\"timeago\" datetime=\"{{ message.created_at }}\">{{ message.created_at }}</time>\n        {% if message.seen_at %}, seen\n        <time class=\"timeago\" datetime=\"{{ message.seen_at }}\">{{ message.seen_at }}</time>{% endif %}.</span>\n\n    <br/>\n    <br/>\n\n    {% if message.data %}\n    <span style=\"white-space: pre-line\">{{ message.data }}</span>\n    {% else %}\n    <small>This message is empty.</small>\n    {% endif %}\n\n    <br/>\n    <br/>\n    <a href=\"/inbox/new?to={{ message.sender }}\" class=\"ui-btn ui-icon-comment ui-btn-icon-left ui-shadow-icon\">Reply</a>\n    <a href=\"/inbox/{{ message.id }}/deleted\" class=\"ui-btn ui-icon-delete ui-btn-icon-left ui-shadow-icon\" onclick=\"return confirm('Are you sure?')\">Delete</a>\n</p>\n{% endblock %}\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/new_message.html",
    "content": "{% extends \"base.html\" %}\n{% set active_page = \"new\" %}\n\n{% block title %}\n{% if to %}\nReply to {{ to }}\n{% else %}\nNew Message\n{% endif %}\n{% endblock %}\n\n{% block script %}\n$(function(){\n    $(\"#message_form\").submit(function(e) {\n          e.preventDefault();\n\n          var form = $(this);\n          var url = form.attr('action');\n\n          $.ajax({\n             type: \"POST\",\n             url: url,\n             data: form.serialize(),\n             success: function(data) {\n                  if( data.error ) {\n                      if( data.error.indexOf('404') != -1 )\n                          alert('Fingerprint not found.');\n                      else if( data.error.indexOf('aborted') != -1 )\n                          alert('Empty or invalid message.');\n                      else\n                          alert(data.error);\n                      return;\n                  }\n\n                  alert(\"Message sent!\");\n                  document.location.href = \"/inbox\";\n            }\n        });\n    });\n});\n{% endblock %}\n\n{% block content %}\n<div style=\"padding: 1em\">\n    <form id=\"message_form\" method=\"POST\" action=\"/inbox/send\">\n        <label for=\"to\">To:</label>\n        <input type=\"text\" name=\"to\" id=\"to\" value=\"{{ to }}\">\n\n        <label for=\"message\">Message:</label>\n        <textarea cols=\"40\" rows=\"8\" name=\"message\" id=\"message\"></textarea>\n        <input type=\"hidden\" name=\"csrf_token\" value=\"{{ csrf_token() }}\"/>\n        <input type=\"submit\" class=\"button\" value=\"Send\"/>\n    </form>\n</div>\n{% endblock %}\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/peers.html",
    "content": "{% extends \"base.html\" %}\n{% set active_page = \"peers\" %}\n\n{% block title %}\n{{ name }} Friends\n{% endblock %}\n\n{% block content %}\n<ul class=\"peers\" data-role=\"listview\" data-filter=\"true\" data-filter-placeholder=\"Search peers...\" data-inset=\"true\">\n    {% for peer in peers %}\n    <li class=\"peer\">\n        <a href=\"/inbox/new?to={{ peer.fingerprint }}\">\n            <h2>{{ peer.advertisement.face }} {{ peer.advertisement.name }}@{{ peer.fingerprint }}</h2>\n            <p>\n                Pwned {{ peer.advertisement.pwnd_tot }} networks, {{ peer.encounters }} encounters.\n            </p>\n        </a>\n    </li>\n    {% endfor %}\n</ul>\n{% endblock %}\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/plugins.html",
    "content": "{% extends \"base.html\" %}\n{% set active_page = \"plugins\" %}\n\n{% block title %}\nPlugins\n{% endblock %}\n\n{% block styles %}\n  {{ super() }}\n  <style>\n  .tooltip {\n    position: relative;\n    display: inline-block;\n  }\n  .tooltip .tooltiptext {\n    visibility: hidden;\n    width: 200px;\n    background-color: #3388cc;\n    color: #fff;\n    text-align: center;\n    border-radius: 10px;\n    border: 2px solid black;\n    padding: 20px 0;\n\n    position: absolute;\n    z-index: 1;\n    top: 100%;\n    left: 50%;\n    margin-left: -100px;\n  }\n\n  .tooltip:hover .tooltiptext {\n    visibility: visible;\n  }\n\n  </style>\n{% endblock %}\n\n{% block script %}\n$(function(){\n    $('input[type=checkbox]').change(function(e) {\n          var checkbox = $(this);\n          var form = checkbox.closest('form');\n          var url = form.attr('action');\n\n          $.ajax({\n             type: 'POST',\n             url: url,\n             data: form.serialize(),\n             success: function(data) {\n                  if( data.indexOf('failed') != -1 ) {\n                      alert('Could not be toggled.');\n                  }\n            }\n        });\n    });\n});\n{% endblock %}\n{% block content %}\n<div id=\"container\">\n    {% for name in database.keys() | sort %}\n        {% set has_info = name in loaded and loaded[name].__description__ is defined %}\n        <div class=\"plugins-box\">\n          <div class=\"tooltip\">\n            <h4>\n              <a {% if name in loaded and loaded[name].on_webhook is defined %} href=\"/plugins/{{name}}\" {% endif %}>{{name}}</a>\n            </h4>\n            {% if has_info %}\n              <span class=\"tooltiptext\">{{ loaded[name].__description__ }}</span>\n            {% else %}\n              <span class=\"tooltiptext\">Description can't be loaded yet.</span>\n            {% endif %}\n          </div>\n          <form method=\"POST\" action=\"/plugins/toggle\">\n            <input type=\"checkbox\" data-role=\"flipswitch\" name=\"enabled\" id=\"flip-checkbox-{{name}}\" data-on-text=\"Enabled\" data-off-text=\"Disabled\" data-wrapper-class=\"custom-size-flipswitch\" {% if name in loaded %} checked {% endif %}>\n            <input type=\"hidden\" name=\"csrf_token\" value=\"{{ csrf_token() }}\"/>\n            <input type=\"hidden\" name=\"plugin\" value=\"{{ name }}\"/>\n          </form>\n        </div>\n    {% endfor %}\n</div>\n{% endblock %}\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/profile.html",
    "content": "{% extends \"base.html\" %}\n{% set active_page = \"profile\" %}\n\n{% block title %}\nProfile\n{% endblock %}\n\n{% block script %}\n$(function(){\n    $('#qrcode').qrcode({\n        text: 'https://pwnagotchi.ai/pwnfile/#{{ fingerprint }}',\n        render: 'div',\n        mode: 0,\n        size: 400,\n        fontname: 'sans',\n        fontcolor: '#000'\n    });\n});\n{% endblock %}\n\n{% block content %}\n<div style=\"padding: 1em\">\n    <label for=\"name\">Name</label>\n    <h4 id=\"name\">{{ name }}</h4>\n\n    <label for=\"fingerprint\">Fingerprint</label>\n    <h4 id=\"fingerprint\">\n        <a href=\"https://pwnagotchi.ai/pwnfile/#{{ fingerprint }}\" target=\"_blank\">{{ fingerprint }}</a>\n    </h4>\n    <div id=\"qrcode\"></div>\n\n    <br/>\n    <label for=\"data\">Data</label>\n    <pre><code id=\"data\">{{ data }}</code></pre>\n</div>\n{% endblock %}\n"
  },
  {
    "path": "pwnagotchi/ui/web/templates/status.html",
    "content": "<html>\n  <head>\n      <title>{{ title }}</title>\n      <meta http-equiv=\"refresh\" content=\"{{ go_back_after }};URL=/\">\n      <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/style.css\"/>\n  </head>\n  <body>\n    <div class=\"status\">\n        {{ message }}\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "pwnagotchi/utils.py",
    "content": "\nimport logging\nimport glob\nimport os\nimport time\nimport subprocess\n\nimport json\nimport shutil\nimport toml\nimport sys\nimport re\n\nfrom toml.encoder import TomlEncoder, _dump_str\nfrom zipfile import ZipFile\nfrom datetime import datetime\nfrom enum import Enum\n\n\nclass DottedTomlEncoder(TomlEncoder):\n    \"\"\"\n    Dumps the toml into the dotted-key format\n    \"\"\"\n\n    def __init__(self, _dict=dict):\n        super(DottedTomlEncoder, self).__init__(_dict)\n\n    def dump_list(self, v):\n        retval = \"[\"\n        # 1 line if its just 1 item; therefore no newline\n        if len(v) > 1:\n            retval += \"\\n\"\n        for u in v:\n            retval += \" \" + str(self.dump_value(u)) + \",\\n\"\n        # 1 line if its just 1 item; remove newline\n        if len(v) <= 1:\n            retval = retval.rstrip(\"\\n\")\n        retval += \"]\"\n        return retval\n\n    def dump_sections(self, o, sup):\n        retstr = \"\"\n        pre = \"\"\n\n        if sup:\n            pre = sup + \".\"\n\n        for section, value in o.items():\n            section = str(section)\n            qsection = section\n            if not re.match(r'^[A-Za-z0-9_-]+$', section):\n                qsection = _dump_str(section)\n            if value is not None:\n                if isinstance(value, dict):\n                    toadd, _ = self.dump_sections(value, pre + qsection)\n                    retstr += toadd\n                    # separte sections\n                    if not retstr.endswith('\\n\\n'):\n                        retstr += '\\n'\n                else:\n                    retstr += (pre + qsection + \" = \" +\n                                str(self.dump_value(value)) + '\\n')\n        return (retstr, self._dict())\n\n\ndef parse_version(version):\n    \"\"\"\n    Converts a version str to tuple, so that versions can be compared\n    \"\"\"\n    return tuple(version.split('.'))\n\n\ndef remove_whitelisted(list_of_handshakes, list_of_whitelisted_strings, valid_on_error=True):\n    \"\"\"\n    Removes a given list of whitelisted handshakes from a path list\n    \"\"\"\n    filtered = list()\n    def normalize(name):\n        \"\"\"\n        Only allow alpha/nums\n        \"\"\"\n        return str.lower(''.join(c for c in name if c.isalnum()))\n\n    for handshake in list_of_handshakes:\n        try:\n            normalized_handshake = normalize(os.path.basename(handshake).rstrip('.pcap'))\n            for whitelist in list_of_whitelisted_strings:\n                normalized_whitelist = normalize(whitelist)\n                if normalized_whitelist in normalized_handshake:\n                    break\n            else:\n                filtered.append(handshake)\n        except Exception:\n            if valid_on_error:\n                filtered.append(handshake)\n    return filtered\n\n\n\ndef download_file(url, destination, chunk_size=128):\n    import requests\n    resp = requests.get(url)\n    resp.raise_for_status()\n\n    with open(destination, 'wb') as fd:\n        for chunk in resp.iter_content(chunk_size):\n            fd.write(chunk)\n\ndef unzip(file, destination, strip_dirs=0):\n    os.makedirs(destination, exist_ok=True)\n    with ZipFile(file, 'r') as zip:\n        if strip_dirs:\n            for info in zip.infolist():\n                new_filename = info.filename.split('/', maxsplit=strip_dirs)[strip_dirs]\n                if new_filename:\n                    info.filename = new_filename\n                    zip.extract(info, destination)\n        else:\n            zip.extractall(destination)\n\n\n# https://stackoverflow.com/questions/823196/yaml-merge-in-python\ndef merge_config(user, default):\n    if isinstance(user, dict) and isinstance(default, dict):\n        for k, v in default.items():\n            if k not in user:\n                user[k] = v\n            else:\n                user[k] = merge_config(user[k], v)\n    return user\n\ndef keys_to_str(data):\n    if isinstance(data,list):\n        converted_list = list()\n        for item in data:\n            if isinstance(item,list) or isinstance(item,dict):\n                converted_list.append(keys_to_str(item))\n            else:\n                converted_list.append(item)\n        return converted_list\n\n    converted_dict = dict()\n    for key, value in data.items():\n        if isinstance(value, list) or isinstance(value, dict):\n            converted_dict[str(key)] = keys_to_str(value)\n        else:\n            converted_dict[str(key)] = value\n\n    return converted_dict\n\ndef save_config(config, target):\n    with open(target, 'wt') as fp:\n        fp.write(toml.dumps(config, encoder=DottedTomlEncoder()))\n    return True\n\ndef load_config(args):\n    default_config_path = os.path.dirname(args.config)\n    if not os.path.exists(default_config_path):\n        os.makedirs(default_config_path)\n\n    import pwnagotchi\n    ref_defaults_file = os.path.join(os.path.dirname(pwnagotchi.__file__), 'defaults.toml')\n    ref_defaults_data = None\n\n    # check for a config.yml file on /boot/\n    for boot_conf in ['/boot/config.yml', '/boot/config.toml']:\n        if os.path.exists(boot_conf):\n            # logging not configured here yet\n            print(\"installing %s to %s ...\", boot_conf, args.user_config)\n            # https://stackoverflow.com/questions/42392600/oserror-errno-18-invalid-cross-device-link\n            shutil.move(boot_conf, args.user_config)\n            break\n\n    # check for an entire pwnagotchi folder on /boot/\n    if os.path.isdir('/boot/pwnagotchi'):\n        print(\"installing /boot/pwnagotchi to /etc/pwnagotchi ...\")\n        shutil.rmtree('/etc/pwnagotchi', ignore_errors=True)\n        shutil.move('/boot/pwnagotchi', '/etc/')\n\n    # if not config is found, copy the defaults\n    if not os.path.exists(args.config):\n        print(\"copying %s to %s ...\" % (ref_defaults_file, args.config))\n        shutil.copy(ref_defaults_file, args.config)\n    else:\n        # check if the user messed with the defaults\n\n        with open(ref_defaults_file) as fp:\n            ref_defaults_data = fp.read()\n\n        with open(args.config) as fp:\n            defaults_data = fp.read()\n\n        if ref_defaults_data != defaults_data:\n            print(\"!!! file in %s is different than release defaults, overwriting !!!\" % args.config)\n            shutil.copy(ref_defaults_file, args.config)\n\n    # load the defaults\n    with open(args.config) as fp:\n        config = toml.load(fp)\n\n    # load the user config\n    try:\n        user_config = None\n        # migrate\n        yaml_name = args.user_config.replace('.toml', '.yml')\n        if not os.path.exists(args.user_config) and os.path.exists(yaml_name):\n            # no toml found; convert yaml\n            logging.info('Old yaml-config found. Converting to toml...')\n            with open(args.user_config, 'w') as toml_file, open(yaml_name) as yaml_file:\n                import yaml\n                user_config = yaml.safe_load(yaml_file)\n                # convert int/float keys to str\n                user_config = keys_to_str(user_config)\n                # convert to toml but use loaded yaml\n                toml.dump(user_config, toml_file)\n        elif os.path.exists(args.user_config):\n            with open(args.user_config) as toml_file:\n                user_config = toml.load(toml_file)\n\n        if user_config:\n            config = merge_config(user_config, config)\n    except Exception as ex:\n        logging.error(\"There was an error processing the configuration file:\\n%s \",ex)\n        sys.exit(1)\n\n    # dropins\n    dropin = config['main']['confd']\n    if dropin and os.path.isdir(dropin):\n        dropin += '*.toml' if dropin.endswith('/') else '/*.toml' # only toml here; yaml is no more\n        for conf in glob.glob(dropin):\n            with open(conf) as toml_file:\n                additional_config = toml.load(toml_file)\n                config = merge_config(additional_config, config)\n\n    # the very first step is to normalize the display name so we don't need dozens of if/elif around\n    if config['ui']['display']['type'] in ('inky', 'inkyphat'):\n        config['ui']['display']['type'] = 'inky'\n\n    elif config['ui']['display']['type'] in ('papirus', 'papi'):\n        config['ui']['display']['type'] = 'papirus'\n\n    elif config['ui']['display']['type'] in ('oledhat',):\n        config['ui']['display']['type'] = 'oledhat'\n\n    elif config['ui']['display']['type'] in ('adafruitssd1306i2c',):\n        config['ui']['display']['type'] = 'adafruitssd1306i2c'\n\n    elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1'):\n        config['ui']['display']['type'] = 'waveshare_1'\n\n    elif config['ui']['display']['type'] in ('ws_2', 'ws2', 'waveshare_2', 'waveshare2'):\n        config['ui']['display']['type'] = 'waveshare_2'\n\n    elif config['ui']['display']['type'] in ('ws_3', 'ws3', 'waveshare_3', 'waveshare3'):\n        config['ui']['display']['type'] = 'waveshare_3'\n\n    elif config['ui']['display']['type'] in ('ws_27inch', 'ws27inch', 'waveshare_27inch', 'waveshare27inch'):\n        config['ui']['display']['type'] = 'waveshare27inch'\n\n    elif config['ui']['display']['type'] in ('ws_29inch', 'ws29inch', 'waveshare_29inch', 'waveshare29inch'):\n        config['ui']['display']['type'] = 'waveshare29inch'\n\n    elif config['ui']['display']['type'] in ('lcdhat',):\n        config['ui']['display']['type'] = 'lcdhat'\n\n    elif config['ui']['display']['type'] in ('dfrobot_1', 'df1'):\n        config['ui']['display']['type'] = 'dfrobot_1'\n\n    elif config['ui']['display']['type'] in ('dfrobot_2', 'df2'):\n        config['ui']['display']['type'] = 'dfrobot_2'\n\n    elif config['ui']['display']['type'] in ('ws_154inch', 'ws154inch', 'waveshare_154inch', 'waveshare154inch'):\n        config['ui']['display']['type'] = 'waveshare154inch'\n\n    elif config['ui']['display']['type'] in ('waveshare144lcd', 'ws_144inch', 'ws144inch', 'waveshare_144inch', 'waveshare144inch'):\n        config['ui']['display']['type'] = 'waveshare144lcd'\n\n    elif config['ui']['display']['type'] in ('ws_213d', 'ws213d', 'waveshare_213d', 'waveshare213d'):\n        config['ui']['display']['type'] = 'waveshare213d'\n\n    elif config['ui']['display']['type'] in ('ws_213bc', 'ws213bc', 'waveshare_213bc', 'waveshare213bc'):\n        config['ui']['display']['type'] = 'waveshare213bc'\n\n    elif config['ui']['display']['type'] in ('ws_213bv4', 'ws213bv4', 'waveshare_213bv4', 'waveshare213inb_v4'):\n        config['ui']['display']['type'] = 'waveshare213inb_v4'\n\n    elif config['ui']['display']['type'] in ('waveshare35lcd'):\n        config['ui']['display']['type'] = 'waveshare35lcd'\n\n    elif config['ui']['display']['type'] in ('spotpear24inch'):\n        config['ui']['display']['type'] = 'spotpear24inch'\n\n    else:\n        print(\"unsupported display type %s\" % config['ui']['display']['type'])\n        sys.exit(1)\n\n    return config\n\n\ndef secs_to_hhmmss(secs):\n    mins, secs = divmod(secs, 60)\n    hours, mins = divmod(mins, 60)\n    return '%02d:%02d:%02d' % (hours, mins, secs)\n\n\ndef total_unique_handshakes(path):\n    expr = os.path.join(path, \"*.pcap\")\n    return len(glob.glob(expr))\n\n\ndef iface_channels(ifname):\n    channels = []\n    output = subprocess.getoutput(\"/sbin/iwlist %s freq\" % ifname)\n    for line in output.split(\"\\n\"):\n        line = line.strip()\n        if line.startswith(\"Channel \"):\n            channels.append(int(line.split()[1]))\n    return channels\n\n\ndef led(on=True):\n    with open('/sys/class/leds/led0/brightness', 'w+t') as fp:\n        fp.write(\"%d\" % (0 if on is True else 1))\n\n\ndef blink(times=1, delay=0.3):\n    for _ in range(0, times):\n        led(True)\n        time.sleep(delay)\n        led(False)\n        time.sleep(delay)\n    led(True)\n\n\nclass WifiInfo(Enum):\n    \"\"\"\n    Fields you can extract from a pcap file\n    \"\"\"\n    BSSID = 0\n    ESSID = 1\n    ENCRYPTION = 2\n    CHANNEL = 3\n    RSSI = 4\n\n\nclass FieldNotFoundError(Exception):\n    pass\n\n\ndef md5(fname):\n    \"\"\"\n    https://stackoverflow.com/questions/3431825/generating-an-md5-checksum-of-a-file\n    \"\"\"\n    import hashlib\n    hash_md5 = hashlib.md5()\n    with open(fname, \"rb\") as f:\n        for chunk in iter(lambda: f.read(4096), b\"\"):\n            hash_md5.update(chunk)\n    return hash_md5.hexdigest()\n\n\ndef extract_from_pcap(path, fields):\n    \"\"\"\n    Search in pcap-file for specified information\n\n    path: Path to pcap file\n    fields: Array of fields that should be extracted\n\n    If a field is not found, FieldNotFoundError is raised\n    \"\"\"\n    results = dict()\n    for field in fields:\n        if not isinstance(field, WifiInfo):\n            raise TypeError(\"Invalid field\")\n\n        subtypes = set()\n\n        if field == WifiInfo.BSSID:\n            from scapy.all import Dot11Beacon, Dot11ProbeResp, Dot11AssoReq, Dot11ReassoReq, Dot11, sniff\n            subtypes.add('beacon')\n            bpf_filter = \" or \".join([f\"wlan type mgt subtype {subtype}\" for subtype in subtypes])\n            packets = sniff(offline=path, filter=bpf_filter)\n            try:\n                for packet in packets:\n                    if packet.haslayer(Dot11Beacon):\n                        if hasattr(packet[Dot11], 'addr3'):\n                            results[field] = packet[Dot11].addr3\n                            break\n                else:  # magic\n                    raise FieldNotFoundError(\"Could not find field [BSSID]\")\n            except Exception:\n                raise FieldNotFoundError(\"Could not find field [BSSID]\")\n        elif field == WifiInfo.ESSID:\n            from scapy.all import Dot11Beacon, Dot11ReassoReq, Dot11AssoReq, Dot11, sniff, Dot11Elt\n            subtypes.add('beacon')\n            subtypes.add('assoc-req')\n            subtypes.add('reassoc-req')\n            bpf_filter = \" or \".join([f\"wlan type mgt subtype {subtype}\" for subtype in subtypes])\n            packets = sniff(offline=path, filter=bpf_filter)\n            try:\n                for packet in packets:\n                    if packet.haslayer(Dot11Elt) and hasattr(packet[Dot11Elt], 'info'):\n                        results[field] = packet[Dot11Elt].info.decode('utf-8')\n                        break\n                else:  # magic\n                    raise FieldNotFoundError(\"Could not find field [ESSID]\")\n            except Exception:\n                raise FieldNotFoundError(\"Could not find field [ESSID]\")\n        elif field == WifiInfo.ENCRYPTION:\n            from scapy.all import Dot11Beacon, sniff\n            subtypes.add('beacon')\n            bpf_filter = \" or \".join([f\"wlan type mgt subtype {subtype}\" for subtype in subtypes])\n            packets = sniff(offline=path, filter=bpf_filter)\n            try:\n                for packet in packets:\n                    if packet.haslayer(Dot11Beacon) and hasattr(packet[Dot11Beacon], 'network_stats'):\n                        stats = packet[Dot11Beacon].network_stats()\n                        if 'crypto' in stats:\n                            results[field] = stats['crypto']  # set with encryption types\n                            break\n                else:  # magic\n                    raise FieldNotFoundError(\"Could not find field [ENCRYPTION]\")\n            except Exception:\n                raise FieldNotFoundError(\"Could not find field [ENCRYPTION]\")\n        elif field == WifiInfo.CHANNEL:\n            from scapy.all import sniff, RadioTap\n            from pwnagotchi.mesh.wifi import freq_to_channel\n            packets = sniff(offline=path, count=1)\n            try:\n                results[field] = freq_to_channel(packets[0][RadioTap].ChannelFrequency)\n            except Exception:\n                raise FieldNotFoundError(\"Could not find field [CHANNEL]\")\n        elif field == WifiInfo.RSSI:\n            from scapy.all import sniff, RadioTap\n            from pwnagotchi.mesh.wifi import freq_to_channel\n            packets = sniff(offline=path, count=1)\n            try:\n                results[field] = packets[0][RadioTap].dBm_AntSignal\n            except Exception:\n                raise FieldNotFoundError(\"Could not find field [RSSI]\")\n\n    return results\n\nclass StatusFile(object):\n    def __init__(self, path, data_format='raw'):\n        self._path = path\n        self._updated = None\n        self._format = data_format\n        self.data = None\n\n        if os.path.exists(path):\n            self._updated = datetime.fromtimestamp(os.path.getmtime(path))\n            with open(path) as fp:\n                if data_format == 'json':\n                    self.data = json.load(fp)\n                else:\n                    self.data = fp.read()\n\n    def data_field_or(self, name, default=\"\"):\n        if self.data is not None and name in self.data:\n            return self.data[name]\n        return default\n\n    def newer_then_minutes(self, minutes):\n        return self._updated is not None and ((datetime.now() - self._updated).seconds / 60) < minutes\n\n    def newer_then_hours(self, hours):\n        return self._updated is not None and ((datetime.now() - self._updated).seconds / (60 * 60)) < hours\n\n    def newer_then_days(self, days):\n        return self._updated is not None and (datetime.now() - self._updated).days < days\n\n    def update(self, data=None):\n        from pwnagotchi.fs import ensure_write\n        self._updated = datetime.now()\n        self.data = data\n        with ensure_write(self._path, 'w') as fp:\n            if data is None:\n                fp.write(str(self._updated))\n\n            elif self._format == 'json':\n                json.dump(self.data, fp)\n\n            else:\n                fp.write(data)\n"
  },
  {
    "path": "pwnagotchi/voice.py",
    "content": "import gettext\nimport os\nimport random\n\n\nclass Voice:\n    def __init__(self, lang):\n        localedir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'locale')\n        translation = gettext.translation(\n            'voice', localedir,\n            languages=[lang],\n            fallback=True,\n        )\n        translation.install()\n        self._ = translation.gettext\n\n    def custom(self, s):\n        return s\n\n    def default(self):\n        return self._('ZzzzZZzzzzZzzz')\n\n    def on_starting(self):\n        return random.choice([\n            self._('Hi, I\\'m Pwnagotchi! Starting ...'),\n            self._('New day, new hunt, new pwns!'),\n            self._('Hack the Planet!')])\n\n    def on_ai_ready(self):\n        return random.choice([\n            self._('AI ready.'),\n            self._('The neural network is ready.')])\n\n    def on_keys_generation(self):\n        return random.choice([\n            self._('Generating keys, do not turn off ...')])\n\n    def on_normal(self):\n        return random.choice([\n            '',\n            '...'])\n\n    def on_free_channel(self, channel):\n        return self._('Hey, channel {channel} is free! Your AP will say thanks.').format(channel=channel)\n\n    def on_reading_logs(self, lines_so_far=0):\n        if lines_so_far == 0:\n            return self._('Reading last session logs ...')\n        else:\n            return self._('Read {lines_so_far} log lines so far ...').format(lines_so_far=lines_so_far)\n\n    def on_bored(self):\n        return random.choice([\n            self._('I\\'m bored ...'),\n            self._('Let\\'s go for a walk!')])\n\n    def on_motivated(self, reward):\n        return self._('This is the best day of my life!')\n\n    def on_demotivated(self, reward):\n        return self._('Shitty day :/')\n\n    def on_sad(self):\n        return random.choice([\n            self._('I\\'m extremely bored ...'),\n            self._('I\\'m very sad ...'),\n            self._('I\\'m sad'),\n            '...'])\n\n    def on_angry(self):\n        # passive aggressive or not? :D\n        return random.choice([\n            '...',\n            self._('Leave me alone ...'),\n            self._('I\\'m mad at you!')])\n\n    def on_excited(self):\n        return random.choice([\n            self._('I\\'m living the life!'),\n            self._('I pwn therefore I am.'),\n            self._('So many networks!!!'),\n            self._('I\\'m having so much fun!'),\n            self._('My crime is that of curiosity ...')])\n\n    def on_new_peer(self, peer):\n        if peer.first_encounter():\n            return random.choice([\n                self._('Hello {name}! Nice to meet you.').format(name=peer.name())])\n        else:\n            return random.choice([\n                self._('Yo {name}! Sup?').format(name=peer.name()),\n                self._('Hey {name} how are you doing?').format(name=peer.name()),\n                self._('Unit {name} is nearby!').format(name=peer.name())])\n\n    def on_lost_peer(self, peer):\n        return random.choice([\n            self._('Uhm ... goodbye {name}').format(name=peer.name()),\n            self._('{name} is gone ...').format(name=peer.name())])\n\n    def on_miss(self, who):\n        return random.choice([\n            self._('Whoops ... {name} is gone.').format(name=who),\n            self._('{name} missed!').format(name=who),\n            self._('Missed!')])\n\n    def on_grateful(self):\n        return random.choice([\n            self._('Good friends are a blessing!'),\n            self._('I love my friends!')])\n\n    def on_lonely(self):\n        return random.choice([\n            self._('Nobody wants to play with me ...'),\n            self._('I feel so alone ...'),\n            self._('Where\\'s everybody?!')])\n\n    def on_napping(self, secs):\n        return random.choice([\n            self._('Napping for {secs}s ...').format(secs=secs),\n            self._('Zzzzz'),\n            self._('ZzzZzzz ({secs}s)').format(secs=secs)])\n\n    def on_shutdown(self):\n        return random.choice([\n            self._('Good night.'),\n            self._('Zzz')])\n\n    def on_awakening(self):\n        return random.choice(['...', '!'])\n\n    def on_waiting(self, secs):\n        return random.choice([\n            self._('Waiting for {secs}s ...').format(secs=secs),\n            '...',\n            self._('Looking around ({secs}s)').format(secs=secs)])\n\n    def on_assoc(self, ap):\n        ssid, bssid = ap['hostname'], ap['mac']\n        what = ssid if ssid != '' and ssid != '<hidden>' else bssid\n        return random.choice([\n            self._('Hey {what} let\\'s be friends!').format(what=what),\n            self._('Associating to {what}').format(what=what),\n            self._('Yo {what}!').format(what=what)])\n\n    def on_deauth(self, sta):\n        return random.choice([\n            self._('Just decided that {mac} needs no WiFi!').format(mac=sta['mac']),\n            self._('Deauthenticating {mac}').format(mac=sta['mac']),\n            self._('Kickbanning {mac}!').format(mac=sta['mac'])])\n\n    def on_handshakes(self, new_shakes):\n        s = 's' if new_shakes > 1 else ''\n        return self._('Cool, we got {num} new handshake{plural}!').format(num=new_shakes, plural=s)\n\n    def on_unread_messages(self, count, total):\n        s = 's' if count > 1 else ''\n        return self._('You have {count} new message{plural}!').format(count=count, plural=s)\n\n    def on_rebooting(self):\n        return self._(\"Oops, something went wrong ... Rebooting ...\")\n\n    def on_uploading(self, to):\n        return self._(\"Uploading data to {to} ...\").format(to=to)\n\n    def on_last_session_data(self, last_session):\n        status = self._('Kicked {num} stations\\n').format(num=last_session.deauthed)\n        if last_session.associated > 999:\n            status += self._('Made >999 new friends\\n')\n        else:\n            status += self._('Made {num} new friends\\n').format(num=last_session.associated)\n        status += self._('Got {num} handshakes\\n').format(num=last_session.handshakes)\n        if last_session.peers == 1:\n            status += self._('Met 1 peer')\n        elif last_session.peers > 0:\n            status += self._('Met {num} peers').format(num=last_session.peers)\n        return status\n\n    def on_last_session_tweet(self, last_session):\n        return self._(\n            'I\\'ve been pwning for {duration} and kicked {deauthed} clients! I\\'ve also met {associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet').format(\n            duration=last_session.duration_human,\n            deauthed=last_session.deauthed,\n            associated=last_session.associated,\n            handshakes=last_session.handshakes)\n\n    def hhmmss(self, count, fmt):\n        if count > 1:\n            # plural\n            if fmt == \"h\":\n                return self._(\"hours\")\n            if fmt == \"m\":\n                return self._(\"minutes\")\n            if fmt == \"s\":\n                return self._(\"seconds\")\n        else:\n            # sing\n            if fmt == \"h\":\n                return self._(\"hour\")\n            if fmt == \"m\":\n                return self._(\"minute\")\n            if fmt == \"s\":\n                return self._(\"second\")\n        return fmt\n"
  },
  {
    "path": "release.stork",
    "content": "#!/usr/bin/env stork -f\n\nversion:parser \"__version__\\\\s*=\\\\s*['\\\"]([\\\\d\\\\.ab]+)[\\\"']\"\nversion:file \"pwnagotchi/_version.py\"\nversion:from_user\n\ngit:create_tag $VERSION"
  },
  {
    "path": "requirements.txt",
    "content": "pycryptodome==3.9.4\nrequests==2.21.0\nPyYAML==5.3.1\nscapy==2.4.3\ngym==0.14.0\nscipy==1.3.1\nstable-baselines==2.7.0\ntensorflow==1.13.1\ntensorflow-estimator==1.14.0\ntweepy==3.7.0\nfile-read-backwards==2.0.0\nnumpy==1.20.2\ninky==1.2.0\nsmbus2==0.3.0\nPillow==5.4.1\nspidev==3.4\ngast==0.2.2\nflask==1.0.2\nflask-cors==3.0.7\nflask-wtf==0.14.3\ndbus-python==1.2.12\ntoml==0.10.0\npython-dateutil==2.8.1\nwebsockets==8.1\n"
  },
  {
    "path": "scripts/backup.sh",
    "content": "#!/bin/sh\n\nusage() {\n\techo \"Usage: backup.sh [-honu] [-h] [-u user] [-n host name or ip] [-o output]\"\n}\n\nwhile getopts \"ho:n:u:\" arg; do\n\tcase $arg in\n\t\th)\n\t\t\tusage\n\t\t\texit\n\t\t\t;;\n\t\tn)\n\t\t\tUNIT_HOSTNAME=$OPTARG\n\t\t\t;;\n\t\to)\n\t\t\tOUTPUT=$OPTARG\n\t\t\t;;\n\t\tu)\n\t\t\tUNIT_USERNAME=$OPTARG\n\t\t\t;;\n\t\t*)\n\t\t\tusage\n\t\t\texit 1\n\tesac\ndone\n\n# name of the ethernet gadget interface on the host\nUNIT_HOSTNAME=${UNIT_HOSTNAME:-10.0.0.2}\n# output backup tgz file\nOUTPUT=${OUTPUT:-${UNIT_HOSTNAME}-backup-$(date +%s).tgz}\n# username to use for ssh\nUNIT_USERNAME=${UNIT_USERNAME:-pi}\n# what to backup\nFILES_TO_BACKUP=\"/root/brain.nn \\\n  /root/brain.json \\\n  /root/.api-report.json \\\n  /root/.ssh \\\n  /root/.bashrc \\\n  /root/.profile \\\n  /root/handshakes \\\n  /root/peers \\\n  /etc/pwnagotchi/ \\\n  /etc/ssh/ \\\n  /var/log/pwnagotchi.log \\\n  /var/log/pwnagotchi*.gz \\\n  /home/pi/.ssh \\\n  /home/pi/.bashrc \\\n  /home/pi/.profile \\\n  /root/.api-report.json \\\n  /root/.auto-update \\\n  /root/.bt-tether* \\\n  /root/.net_pos_saved \\\n  /root/.ohc_uploads \\\n  /root/.wigle_uploads \\\n  /root/.wpa_sec_uploads\"\n\nping -c 1 \"${UNIT_HOSTNAME}\" > /dev/null 2>&1 || {\n  echo \"@ unit ${UNIT_HOSTNAME} can't be reached, make sure it's connected and a static IP assigned to the USB interface.\"\n  exit 1\n}\n\necho \"@ backing up $UNIT_HOSTNAME to $OUTPUT ...\"\nssh \"${UNIT_USERNAME}@${UNIT_HOSTNAME}\" \"sudo find ${FILES_TO_BACKUP} -type f -print0 | xargs -0 sudo tar cv\" | gzip -9 > \"$OUTPUT\"\n"
  },
  {
    "path": "scripts/language.sh",
    "content": "#!/bin/bash\n\nset -eu\n\nDEPENDENCIES=( 'xgettext' 'msgfmt' 'msgmerge' )\nCOMMANDS=( 'add' 'update' 'delete' 'compile' )\n\nREPO_DIR=\"$(dirname \"$(dirname \"$(realpath \"$0\")\")\")\"\nLOCALE_DIR=\"${REPO_DIR}/pwnagotchi/locale\"\nVOICE_FILE=\"${REPO_DIR}/pwnagotchi/voice.py\"\n\nfunction usage() {\ncat <<EOF\n\nusage: $0 <command> [options]\n\n  Commands:\n    add <language>\n    delete <language>\n    compile <language>\n    update <language>\n\nEOF\n}\n\nfor REQ in \"${DEPENDENCIES[@]}\"; do\n  if ! type \"$REQ\" >/dev/null 2>&1; then\n    echo \"Dependency check failed for ${REQ}\"\n    exit 1\n  fi\ndone\n\n\nif [[ ! \"${COMMANDS[*]}\" =~ $1 ]]; then\n  usage\nfi\n\n\nfunction add_lang() {\n  mkdir -p \"$LOCALE_DIR/$1/LC_MESSAGES\"\n  cp -n \"$LOCALE_DIR/voice.pot\" \"$LOCALE_DIR/$1/LC_MESSAGES/voice.po\"\n}\n\nfunction del_lang() {\n  # set -eu is present; so not dangerous\n  rm -rf \"$LOCALE_DIR/$1\"\n}\n\nfunction comp_lang() {\n  msgfmt -o  \"$LOCALE_DIR/$1/LC_MESSAGES/voice.mo\"  \"$LOCALE_DIR/$1/LC_MESSAGES/voice.po\"\n}\n\nfunction update_lang() {\n  xgettext --no-location -d voice -o \"$LOCALE_DIR/voice.pot\" \"$VOICE_FILE\"\n  msgmerge --update \"$LOCALE_DIR/$1/LC_MESSAGES/voice.po\" \"$LOCALE_DIR/voice.pot\"\n}\n\n\ncase \"$1\" in\n  add)\n    add_lang \"$2\"\n    ;;\n  delete)\n    del_lang \"$2\"\n    ;;\n  compile)\n    comp_lang \"$2\"\n    ;;\n  update)\n    update_lang \"$2\"\n    ;;\nesac\n"
  },
  {
    "path": "scripts/linux_connection_share.sh",
    "content": "#!/usr/bin/env bash\nset -e\n\n# name of the ethernet gadget interface on the host\nUSB_IFACE=${1:-enp0s20f0u1}\nUSB_IFACE_IP=10.0.0.1\nUSB_IFACE_NET=10.0.0.0/24\n# host interface to use for upstream connection\nUPSTREAM_IFACE=${2:-enxe4b97aa99867}\n\nip addr add \"$USB_IFACE_IP/24\" dev \"$USB_IFACE\"\nip link set \"$USB_IFACE\" up\n\niptables -A FORWARD -o \"$UPSTREAM_IFACE\" -i \"$USB_IFACE\" -s \"$USB_IFACE_NET\" -m conntrack --ctstate NEW -j ACCEPT\niptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT\niptables -t nat -F POSTROUTING\niptables -t nat -A POSTROUTING -o \"$UPSTREAM_IFACE\" -j MASQUERADE\n\necho 1 > /proc/sys/net/ipv4/ip_forward\n"
  },
  {
    "path": "scripts/macos_connection_share.sh",
    "content": "#!/usr/bin/env bash\n\nUPSTREAM_IFACE=${1:-en0}\nUSB_IFACE=''\nUSB_IP=${2:-10.0.0.1}\n\nfor i in $(ifconfig -lu); do\n  if ifconfig $i | grep -q \"${USB_IP}\" ; then USB_IFACE=$i; fi;\ndone\n\nif [ -z \"$USB_IFACE\" ]\nthen\n  echo \"can't find usb interface with ip $USB_IP\"\n  exit 1\nfi\n\necho \"sharing connecting from upstream interface $UPSTREAM_IFACE to usb interface $USB_IFACE ...\"\n\nsysctl -w net.inet.ip.forwarding=1\npfctl -e\necho \"nat on ${UPSTREAM_IFACE} from ${USB_IFACE}:network to any -> (${UPSTREAM_IFACE})\" | pfctl -f -\n"
  },
  {
    "path": "scripts/openbsd_connection_share.sh",
    "content": "#!/bin/sh\n\nUSB_IFACE=$(ifconfig urndis0 | grep urndis0 | awk '{print $1}' | tr -d ':')\nUSB_IP=${2:-10.0.0.1}\n\nif test $(whoami) != root; then\n\tdoas \"$0\" \"$@\"\n\texit $?\nfi\n\nif [ \"${USB_IFACE}\" == \"urndis0\" ]; then\n\tifconfig ${USB_IFACE} ${USB_IP}\n\tsysctl -w net.inet.ip.forwarding=1\n\techo \"match out on egress inet from ${USB_IFACE}:network to any nat-to (egress:0)\" | pfctl -f -\n\tpfctl -f /etc/pf.conf\n\techo \"sharing connecting from upstream interface to usb interface ${USB_IFACE} ...\"\nelse\n\techo \"can't find usb interface with ip ${USB_IFACE}\"\n\texit 1\nfi\n"
  },
  {
    "path": "scripts/preview.py",
    "content": "#!/usr/bin/env python3\nimport sys\nimport os\nimport argparse\nimport yaml\nimport toml\n\nsys.path.insert(0,\n                os.path.join(os.path.dirname(os.path.realpath(__file__)),\n                             '../'))\n\nimport pwnagotchi.ui.faces as faces\nfrom pwnagotchi.ui.display import Display\nfrom PIL import Image\n\n\nclass CustomDisplay(Display):\n\n    def __init__(self, config, state):\n        self.last_image = None\n        super(CustomDisplay, self).__init__(config, state)\n\n    def _http_serve(self):\n        # do nothing\n        pass\n\n    def _on_view_rendered(self, img):\n        self.last_image = img\n\n    def get_image(self):\n        \"\"\"\n        Return the saved image\n        \"\"\"\n        return self.last_image\n\n\nclass DummyPeer:\n\n    def __init__(self):\n        self.rssi = -50\n\n    @staticmethod\n    def name():\n        return \"beta\"\n\n    @staticmethod\n    def pwnd_run():\n        return 50\n\n    @staticmethod\n    def pwnd_total():\n        return 100\n\n    @staticmethod\n    def first_encounter():\n        return 1\n\n    @staticmethod\n    def face():\n        return faces.FRIEND\n\n\ndef append_images(images, horizontal=True, xmargin=0, ymargin=0):\n    w, h = zip(*(i.size for i in images))\n\n    if horizontal:\n        t_w = sum(w)\n        t_h = max(h)\n    else:\n        t_w = max(w)\n        t_h = sum(h)\n\n    result = Image.new('RGB', (t_w, t_h))\n\n    x_offset = 0\n    y_offset = 0\n\n    for im in images:\n        result.paste(im, (x_offset, y_offset))\n        if horizontal:\n            x_offset += im.size[0] + xmargin\n        else:\n            y_offset += im.size[1] + ymargin\n\n    return result\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"This program emulates\\\n                                     the pwnagotchi display\")\n    parser.add_argument('--displays', help=\"Which displays to use.\", nargs=\"+\", default=[\"waveshare_2\"])\n    parser.add_argument('--lang', help=\"Language to use\",\n                        default=\"en\")\n    parser.add_argument('--output', help=\"Path to output image (PNG)\", default=\"preview.png\")\n    parser.add_argument('--show-peer', dest=\"showpeer\", help=\"This options will show a dummy peer\", action=\"store_true\")\n    parser.add_argument('--xmargin', help=\"Add X-Margin\", type=int, default=5)\n    parser.add_argument('--ymargin', help=\"Add Y-Margin\", type=int, default=5)\n    args = parser.parse_args()\n\n    config_template = '''\n    main:\n        lang: {lang}\n    ui:\n        fps: 0.3\n        display:\n            enabled: false\n            rotation: 180\n            color: black\n            refresh: 30\n            type: {display}\n            web:\n                enabled: true\n                address: \"0.0.0.0\"\n                port: 8080\n\n        faces:\n            look_r: '( ⚆_⚆)'\n            look_l: '(☉_☉ )'\n            look_r_happy: '( ◕‿◕)'\n            look_l_happy: '(◕‿◕ )'\n            sleep: '(⇀‿‿↼)'\n            sleep2: '(≖‿‿≖)'\n            awake: '(◕‿‿◕)'\n            bored: '(-__-)'\n            intense: '(°▃▃°)'\n            cool: '(⌐■_■)'\n            happy: '(•‿‿•)'\n            excited: '(ᵔ◡◡ᵔ)'\n            grateful: '(^‿‿^)'\n            motivated: '(☼‿‿☼)'\n            demotivated: '(≖__≖)'\n            smart: '(✜‿‿✜)'\n            lonely: '(ب__ب)'\n            sad: '(╥☁╥ )'\n            friend: '(♥‿‿♥)'\n            broken: '(☓‿‿☓)'\n            debug: '(#__#)'\n    '''\n\n    list_of_displays = list()\n    for display_type in args.displays:\n        config = yaml.safe_load(config_template.format(display=display_type,\n                                                       lang=args.lang))\n        display = CustomDisplay(config=config, state={'name': f\"{display_type}>\"})\n        list_of_displays.append(display)\n\n    columns = list()\n\n    for display in list_of_displays:\n        emotions = list()\n        if args.showpeer:\n            display.set_closest_peer(DummyPeer(), 10)\n        display.on_starting()\n        display.update()\n        emotions.append(display.get_image())\n        display.on_ai_ready()\n        display.update()\n        emotions.append(display.get_image())\n        display.on_normal()\n        display.update()\n        emotions.append(display.get_image())\n        display.on_new_peer(DummyPeer())\n        display.update()\n        emotions.append(display.get_image())\n        display.on_lost_peer(DummyPeer())\n        display.update()\n        emotions.append(display.get_image())\n        display.on_free_channel('6')\n        display.update()\n        emotions.append(display.get_image())\n        display.wait(2)\n        display.update()\n        emotions.append(display.get_image())\n        display.on_bored()\n        display.update()\n        emotions.append(display.get_image())\n        display.on_sad()\n        display.update()\n        emotions.append(display.get_image())\n        display.on_motivated(1)\n        display.update()\n        emotions.append(display.get_image())\n        display.on_demotivated(-1)\n        display.update()\n        emotions.append(display.get_image())\n        display.on_excited()\n        display.update()\n        emotions.append(display.get_image())\n        display.on_deauth({'mac': 'DE:AD:BE:EF:CA:FE'})\n        display.update()\n        emotions.append(display.get_image())\n        display.on_miss('test')\n        display.update()\n        emotions.append(display.get_image())\n        display.on_lonely()\n        display.update()\n        emotions.append(display.get_image())\n        display.on_handshakes(1)\n        display.update()\n        emotions.append(display.get_image())\n        display.on_rebooting()\n        display.update()\n        emotions.append(display.get_image())\n\n        # append them all together (vertical)\n        columns.append(append_images(emotions, horizontal=False, xmargin=args.xmargin, ymargin=args.ymargin))\n\n    # append columns side by side\n    final_image = append_images(columns, horizontal=True, xmargin=args.xmargin, ymargin=args.ymargin)\n    final_image.save(args.output, 'PNG')\n\n\nif __name__ == '__main__':\n    SystemExit(main())\n"
  },
  {
    "path": "scripts/pypi_upload.sh",
    "content": "#!/bin/bash\n\nrm -rf build dist pwnagotchi.egg-info &&\n  python3 setup.py sdist bdist_wheel &&\n  clear &&\n  twine upload dist/*\n"
  },
  {
    "path": "scripts/restore.sh",
    "content": "#!/bin/sh\n\nusage() {\n\techo \"Usage: restore.sh [-bhnu] [-h] [-b backup name] [-n host name] [-u user name]\"\n}\n\nwhile getopts \"hb:n:u:\" arg; do\n\tcase $arg in\n\t\tb)\n\t\t\tBACKUP=$OPTARG\n\t\t\t;;\n\t\th)\n\t\t\tusage\n\t\t\texit\n\t\t\t;;\n\t\tn)\n\t\t\tUNIT_HOSTNAME=$OPTARG\n\t\t\t;;\n\t\tu)\n\t\t\tUNIT_USERNAME=$OPTARG\n\t\t\t;;\n\t\t*)\n\t\t\tusage\n\t\t\texit 1\n\tesac\ndone\n# name of the ethernet gadget interface on the host\nUNIT_HOSTNAME=${UNIT_HOSTNAME:-10.0.0.2}\n# output backup tgz file\nif [ -z $BACKUP ]; then\n\tBACKUP=$(ls -rt ${UNIT_HOSTNAME}-backup-*.tgz 2>/dev/null | tail -n1)\n\tif [ -z $BACKUP ]; then\n\t\techo \"@ Can't find backup file. Please specify one with '-b'\"\n\t\texit 1\n\tfi\n\techo \"@ Found backup file:\"\n\techo \"\\t${BACKUP}\"\n\techo -n \"@ continue restroring this file? (y/n) \"\n\tread CONTINUE\n\tCONTINUE=$(echo \"${CONTINUE}\" | tr \"[:upper:]\" \"[:lower:]\")\n\tif [ \"${CONTINUE}\" != \"y\" ]; then\n\t\texit 1\n\tfi\nfi\n# username to use for ssh\nUNIT_USERNAME=${UNIT_USERNAME:-pi}\n\nping -c 1 \"${UNIT_HOSTNAME}\" > /dev/null 2>&1 || {\n  echo \"@ unit ${UNIT_HOSTNAME} can't be reached, make sure it's connected and a static IP assigned to the USB interface.\"\n  exit 1\n}\n\necho \"@ restoring $BACKUP to $UNIT_HOSTNAME ...\"\ncat ${BACKUP} | ssh \"${UNIT_USERNAME}@${UNIT_HOSTNAME}\" \"sudo tar xzv -C /\"\n"
  },
  {
    "path": "scripts/win_connection_share.ps1",
    "content": "<#\r\n    .SYNOPSIS\r\n        A script that setups Internet Connection Sharing for Pwnagotchi.\r\n    \r\n    .DESCRIPTION\r\n        A script that setups Internet Connection Sharing for Pwnagotchi. \r\n\r\n        Note: Internet Connection Sharing on Windows can be a bit unstable on between reboots.\r\n              You might need to run this script occasionally to disable and re-enable Internet Connection Sharing.\r\n    \r\n    .PARAMETER EnableInternetConnectionSharing\r\n        Enable Internet Connection Sharing\r\n    \r\n    .PARAMETER DisableInternetConnectionSharing\r\n        Disable Internet Connection Sharing\r\n    \r\n    .PARAMETER SetPwnagotchiSubnet\r\n        Change the Internet Connection Sharing subnet to the Pwnagotchi subnet. The USB Gadget Interface IP will default to 10.0.0.1.\r\n    \r\n    .PARAMETER ScopeAddress\r\n        Custom ScopeAddress (The IP Address of the USB Gadget Interface.)\r\n    \r\n    .EXAMPLE\r\n        # Enable Internet Connection Sharing\r\n        PS C:\\> .\\win_connection_share -EnableInternetConnectionSharing\r\n\r\n    .EXAMPLE\r\n        # Disable Internet Connection Sharing\r\n        PS C:\\> .\\win_connection_share -DisableInternetConnectionSharing\r\n\r\n    .EXAMPLE\r\n        # Change the regkeys of Internet Connection Sharing to the Pwnagotchi Subnet\r\n        PS C:\\> .\\win_connection_share -SetPwnagotchiSubnet\r\n\r\n    .EXAMPLE\r\n        # Change the regkeys of Internet Connection Sharing to the Pwnagotchi Subnet with a custom ScopeAddress (The IP Address of the USB Gadget Interface.)\r\n        PS C:\\> .\\win_connection_share -SetPwnagotchiSubnet -ScopeAddress 10.0.0.10\r\n#>\r\n\r\n#Requires -Version 5\r\n#Requires -RunAsAdministrator\r\n[Cmdletbinding()]\r\nParam (\r\n    [switch]$EnableInternetConnectionSharing,\r\n    [switch]$DisableInternetConnectionSharing,\r\n    [switch]$SetPwnagotchiSubnet,\r\n    [ipaddress]$ScopeAddress = '10.0.0.1'\r\n)\r\n\r\n# Load helper functions\r\nFunction Create-HNetObjects {\r\n    <#\r\n    .SYNOPSIS\r\n        A helper function that does the heavy lifting with NetCfg.HNetShare\r\n    \r\n    .DESCRIPTION\r\n        A helper function that does the heavy lifting with NetCfg.HNetShare. This returns a PSObject containing the `INetSharingConfigurationForINetConnection` info of 2 Adapters.\r\n    \r\n    .PARAMETER InternetAdaptor\r\n        The output of Get-NetAdaptor filtered down to the 'main' uplink interface.\r\n    \r\n    .PARAMETER RNDISGadget\r\n        The output of Get-NetAdaptor filtered down to the 'USB Ethernet/RNDIS Gadget' interface.\r\n    \r\n    .EXAMPLE\r\n        PS> $HNetObject = Create-HNetObjects\r\n        PS> $HNetObject\r\n            RNDISIntConfig     InternetIntConfig\r\n            --------------     -----------------\r\n            System.__ComObject System.__ComObject\r\n    #>\r\n    [Cmdletbinding()]\r\n    Param (\r\n        $InternetAdaptor = $(Select-NetAdaptor -Message \"Please select your main a ethernet adaptor with internet access that will be used for internet sharing.\"),\r\n        $RNDISGadget = $(Select-NetAdaptor -Message \"Please select your 'USB Ethernet/RNDIS Gadget' adaptor\")\r\n    )\r\n    Begin {\r\n        regsvr32.exe /s hnetcfg.dll\r\n        $HNetShare = New-Object -ComObject HNetCfg.HNetShare\r\n    }\r\n    Process {\r\n        if ($HNetShare.EnumEveryConnection -ne $null) {\r\n            $InternetInt       = $HNetShare.EnumEveryConnection | Where-Object { $HNetShare.NetConnectionProps.Invoke($_).Name -eq ($InternetAdaptor).Name }\r\n            $InternetIntConfig = $HNetShare.INetSharingConfigurationForINetConnection.Invoke($InternetInt)\r\n            $RNDISInt          = $HNetShare.EnumEveryConnection | Where-Object { $HNetShare.NetConnectionProps.Invoke($_).Name -eq ($RNDISGadget).Name }\r\n            $RNDISIntConfig    = $HNetShare.INetSharingConfigurationForINetConnection.Invoke($RNDISInt)\r\n        }\r\n    }\r\n    End {\r\n        Return $(New-Object -TypeName PSObject -Property @{InternetIntConfig=$InternetIntConfig;RNDISIntConfig=$RNDISIntConfig;})\r\n    }\r\n}\r\nFunction Enable-InternetConnectionSharing {\r\n    <#\r\n    .SYNOPSIS\r\n        Enables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface.\r\n    \r\n    .DESCRIPTION\r\n        Enables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface.\r\n    \r\n    .EXAMPLE\r\n        PS> Enable-InternetConnectionSharing\r\n    \r\n    #>\r\n    [Cmdletbinding()]\r\n    $HNetObject = Create-HNetObjects\r\n    $HNetObject.InternetIntConfig.EnableSharing(0)\r\n    $HNetObject.RNDISIntConfig.EnableSharing(1)\r\n    Write-Output \"[x] Enabled Internet Connection Sharing.\"\r\n}\r\nFunction Disable-InternetConnectionSharing {\r\n    <#\r\n    .SYNOPSIS\r\n        Disables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface.\r\n    \r\n    .DESCRIPTION\r\n        Disables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface.\r\n\r\n    .EXAMPLE\r\n        PS> Disable-InternetConnectionSharing\r\n    \r\n    #>\r\n    [Cmdletbinding()]\r\n    $HNetObject = $(Create-HNetObjects)\r\n    $HNetObject.InternetIntConfig.DisableSharing()\r\n    $HNetObject.RNDISIntConfig.DisableSharing()\r\n    Write-Output \"[x] Disabled Internet Connection Sharing.\"\r\n}\r\nFunction Test-PwnagotchiSubnet {\r\n    <#\r\n    .SYNOPSIS\r\n        Tests the registry for the correct ScopeAddress.\r\n    \r\n    .DESCRIPTION\r\n        Tests the registry for the correct ScopeAddress. By default windows uses a 192.168.137.x subnet for Internet Connection Sharing. This value can be changed\r\n        in the registry.\r\n    \r\n    .EXAMPLE\r\n        PS> Test-PwnagotchiSubnet\r\n        [!] By default Internet Connection Sharing uses a 192.168.137.x subnet. Run Set-PwnagotchiSubnet to ensure you and your little friend are on the same subnet.\r\n    #>\r\n    [Cmdletbinding()]\r\n    $RegKeys = Get-ItemProperty HKLM:\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters -ErrorAction Stop\r\n    If ($RegKeys.ScopeAddress -notmatch '10.0.0.') {\r\n        Write-Error \"By default Internet Connection Sharing uses a 192.168.137.x subnet. Run Set-PwnagotchiSubnet to ensure you and your little friend are on the same subnet.\" -ErrorAction Stop\r\n    }\r\n    If ($RegKeys.ScopeAddressBackup -notmatch '10.0.0.') {\r\n        Write-Error \"By default Internet Connection Sharing uses a 192.168.137.x subnet. Run Set-PwnagotchiSubnet to ensure you and your little friend are on the same subnet.\" -ErrorAction Stop\r\n    } \r\n}\r\nFunction Set-PwnagotchiSubnet {\r\n    <#\r\n    .SYNOPSIS\r\n        Set the registry for the correct ScopeAddress.\r\n    \r\n    .DESCRIPTION\r\n        Set the registry for the correct ScopeAddress. By default windows uses a 192.168.137.x subnet for Internet Connection Sharing. This value can be changed\r\n        in the registry. By default it will be changed to 10.0.0.1\r\n    \r\n    .PARAMETER ScopeAddress\r\n        The IP address the USB Gadget interface should use.\r\n    \r\n    .EXAMPLE\r\n    Set-PwnagotchiSubnet\r\n    \r\n    #>\r\n    [Cmdletbinding()]\r\n    Param (\r\n        $ScopeAddress = '10.0.0.1'\r\n    )\r\n    Try {\r\n        [void]([ipaddress]$ScopeAddress)\r\n        [void]([byte[]] $ScopeAddress.split('.'))\r\n    } Catch {\r\n        Write-Error \"$ScopeAddress is not a valid IP.\"\r\n    }\r\n    Try {\r\n        Set-ItemProperty -Name ScopeAddress       -Path \"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\\" -Value $ScopeAddress -ErrorAction Stop\r\n        Set-ItemProperty -Name ScopeAddressBackup -Path \"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\\" -Value $ScopeAddress -ErrorAction Stop\r\n        Write-Warning \"The Internet Connection Sharing subnet has been updated. A reboot of windows is required !\"\r\n    } Catch {\r\n        $PSCmdlet.ThrowTerminatingError($PSItem)\r\n    }\r\n \r\n}\r\n\r\n# Main Function\r\nFunction Setup-PwnagotchiNetwork {\r\n    <#\r\n    .SYNOPSIS\r\n        Function to setup networking.\r\n    \r\n    .DESCRIPTION\r\n        Function to setup networking. Main function calls helpers functions.\r\n    \r\n    .PARAMETER EnableInternetConnectionSharing\r\n        Enable Internet Connection Sharing\r\n    \r\n    .PARAMETER DisableInternetConnectionSharing\r\n        Disable Internet Connection Sharing\r\n    \r\n    .PARAMETER SetPwnagotchiSubnet\r\n        Change the Internet Connection Sharing subnet to the Pwnagotchi. Defaults to 10.0.0.1.\r\n    \r\n    .PARAMETER ScopeAddress\r\n        Custom ScopeAddress (the ICS ip address)\r\n    \r\n    .EXAMPLE\r\n        PS> Setup-PwnagotchiNetwork -EnableInternetConnectionSharing\r\n    \r\n    #>\r\n    \r\n    Param (\r\n        [switch]$EnableInternetConnectionSharing,\r\n        [switch]$DisableInternetConnectionSharing,\r\n        [switch]$SetPwnagotchiSubnet,\r\n        $ScopeAddress = '10.0.0.1'\r\n    )\r\n    Begin {\r\n        Try {\r\n            Write-Debug \"Begin\"\r\n            $ErrorSplat=@{ErrorAction=\"stop\"}\r\n            Write-Debug \"Testing subnet\"\r\n            Try {\r\n                Test-PwnagotchiSubnet @ErrorSplat\r\n            } Catch {\r\n                If ($SetPwnagotchiSubnet) {\r\n                    Write-Debug \"Setting subnet\"\r\n                    Set-PwnagotchiSubnet -ScopeAddress $ScopeAddress @ErrorSplat\r\n                } Else {\r\n                    Write-Error \"By default Internet Connection Sharing uses a 192.168.137.x subnet. Run this script with the -SetPwnagotchiSubnet to setup the network.\" -ErrorAction Stop\r\n                }\r\n            }\r\n        } Catch {\r\n            $PSCmdlet.ThrowTerminatingError($PSItem)\r\n        }\r\n    }\r\n    Process {\r\n        Write-Debug \"Process\"\r\n        Try {\r\n            If ($EnableInternetConnectionSharing) {\r\n                Write-Debug \"Enable network Sharing\"\r\n                Enable-InternetConnectionSharing @ErrorSplat\r\n            } ElseIf ($DisableInternetConnectionSharing) {\r\n                Write-Debug \"Disable network Sharing\"\r\n                Disable-InternetConnectionSharing @ErrorSplat\r\n            }\r\n        } Catch {\r\n            $PSCmdlet.ThrowTerminatingError($PSItem)\r\n        }\r\n    }\r\n    End {\r\n        Write-Debug \"End\"\r\n        Try {\r\n            # Nothing to return.\r\n        } Catch {\r\n            $PSCmdlet.ThrowTerminatingError($PSItem)\r\n        }\r\n    }\r\n}\r\nFunction Select-NetAdaptor {\r\n    <#\r\n    .SYNOPSIS\r\n        A menu function to select the correct network adaptors.\r\n    \r\n    .DESCRIPTION\r\n        A menu function to select the correct network adaptors.\r\n    \r\n    .PARAMETER Message\r\n        Message that will be displayed during the question.\r\n    \r\n    #>\r\n    \r\n    Param (\r\n        $Message\r\n    )\r\n    $Adaptors = Get-NetAdapter | Where-Object {$_.MediaConnectionState -eq 'Connected'} | Sort-Object LinkSpeed -Descending\r\n    do { \r\n        Write-Host $Message\r\n        $index = 1\r\n        foreach ($Adaptor in $Adaptors) {\r\n            Write-Host \"[$index] $($Adaptor.Name), $($Adaptor.InterfaceDescription)\"\r\n            $index++\r\n        }   \r\n        $Selection = Read-Host \"Number\"\r\n    } until ($Adaptors[$selection-1])\r\n     Return $Adaptors[$selection-1]\r\n}\r\n# Dynamically create params for Setup-PwnagotchiNetwork function based of param input of script.\r\nSetup-PwnagotchiNetwork @psBoundParameters\r\n"
  },
  {
    "path": "setup.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\nfrom setuptools import setup, find_packages\nfrom distutils.util import strtobool\nimport os\nimport glob\nimport shutil\nimport re\n\n\ndef install_file(source_filename, dest_filename):\n    # do not overwrite network configuration if it exists already\n    # https://github.com/evilsocket/pwnagotchi/issues/483\n    if dest_filename.startswith('/etc/network/interfaces.d/') and os.path.exists(dest_filename):\n        print(\"%s exists, skipping ...\" % dest_filename)\n        return\n\n    print(\"installing %s to %s ...\" % (source_filename, dest_filename))\n    try:\n        dest_folder = os.path.dirname(dest_filename)\n        if not os.path.isdir(dest_folder):\n            os.makedirs(dest_folder)\n\n        shutil.copyfile(source_filename, dest_filename)\n    except Exception as e:\n        print(\"error installing %s: %s\" % (source_filename, e))\n\n\ndef install_system_files():\n    setup_path = os.path.dirname(__file__)\n    data_path = os.path.join(setup_path, \"builder/data\")\n\n    for source_filename in glob.glob(\"%s/**\" % data_path, recursive=True):\n        if os.path.isfile(source_filename):\n            dest_filename = source_filename.replace(data_path, '')\n            install_file(source_filename, dest_filename)\n\n    # reload systemd units\n    os.system(\"systemctl daemon-reload\")\n\n\ndef installer():\n    install_system_files()\n    # for people updating https://github.com/evilsocket/pwnagotchi/pull/551/files\n    os.system(\"systemctl enable fstrim.timer\")\n\ndef version(version_file):\n    with open(version_file, 'rt') as vf:\n        version_file_content = vf.read()\n\n    version_match = re.search(r\"__version__\\s*=\\s*[\\\"\\']([^\\\"\\']+)\", version_file_content)\n    if version_match:\n        return version_match.groups()[0]\n\n    return None\n\n\nif strtobool(os.environ.get(\"PWNAGOTCHI_ENABLE_INSTALLER\", \"1\")):\n    installer()\n\nwith open('requirements.txt') as fp:\n    required = [line.strip() for line in fp if line.strip() != \"\"]\n\nVERSION_FILE = 'pwnagotchi/_version.py'\npwnagotchi_version = version(VERSION_FILE)\n\nsetup(name='pwnagotchi',\n      version=pwnagotchi_version,\n      description='(⌐■_■) - Deep Reinforcement Learning instrumenting bettercap for WiFI pwning.',\n      author='evilsocket && the dev team',\n      author_email='evilsocket@gmail.com',\n      url='https://pwnagotchi.ai/',\n      license='GPL',\n      install_requires=required,\n      scripts=['bin/pwnagotchi'],\n      package_data={'pwnagotchi': ['defaults.yml', 'pwnagotchi/defaults.yml', 'locale/*/LC_MESSAGES/*.mo']},\n      include_package_data=True,\n      packages=find_packages(),\n      classifiers=[\n          'Programming Language :: Python :: 3',\n          'Development Status :: 5 - Production/Stable',\n          'License :: OSI Approved :: GNU General Public License (GPL)',\n          'Environment :: Console',\n      ])\n"
  }
]