[
  {
    "path": ".devcontainer/Dockerfile",
    "content": "# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.222.0/containers/javascript-node/.devcontainer/base.Dockerfile\n\n# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 16, 14, 12, 16-bullseye, 14-bullseye, 12-bullseye, 16-buster, 14-buster, 12-buster\nARG VARIANT=\"24\"\nFROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}\n\nRUN apt-get update && export DEBIAN_FRONTEND=noninteractive \\\n    && apt-get -y install --no-install-recommends bundler\n\n# [Optional] Uncomment if you want to install an additional version of node using nvm\n# ARG EXTRA_NODE_VERSION=10\n# RUN su node -c \"source/usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}\"\n\n# [Optional] Uncomment if you want to install more global node modules\n# RUN su node -c \"npm install -g <your-package-list-here>\" \n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:\n// https://github.com/microsoft/vscode-dev-containers/tree/v0.222.0/containers/javascript-node\n{\n\t\"name\": \"Node.js\",\n\t\"build\": {\n\t\t\"dockerfile\": \"Dockerfile\",\n\t\t// Update 'VARIANT' to pick a Node version: 16, 14, 12.\n\t\t// Append -bullseye or -buster to pin to an OS version.\n\t\t// Use -bullseye variants on local arm64/Apple Silicon.\n\t\t\"args\": { \"VARIANT\": \"24\" }\n\t},\n\n\t// Set *default* container specific settings.json values on container create.\n\t\"settings\": {},\n\n\t// Add the IDs of extensions you want installed when the container is created.\n\t\"extensions\": [\n\t\t\"dbaeumer.vscode-eslint\"\n\t],\n\n\t// Use 'forwardPorts' to make a list of ports inside the container available locally.\n\t// \"forwardPorts\": [],\n\n\t// Use 'postCreateCommand' to run commands after the container is created.\n\t\"postCreateCommand\": \"npm i && cd docs && sudo bundle install\",\n\n\t// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.\n\t\"remoteUser\": \"node\",\n\t\"features\": {\n\t\t\"git\": \"latest\"\n\t}\n}\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"root\": true,\n  \"plugins\": [\"github\"],\n  \"extends\": [\"plugin:github/recommended\", \"plugin:github/typescript\", \"plugin:github/browser\"],\n  \"rules\": {\n    \"import/no-unresolved\": \"off\",\n    \"github/no-inner-html\": \"off\",\n    \"i18n-text/no-en\": \"off\",\n    \"import/extensions\": [\"error\", \"ignorePackages\"],\n    \"@typescript-eslint/consistent-type-imports\": [\"error\", {\"prefer\": \"type-imports\"}]\n  },\n  \"overrides\": [\n    {\n      \"files\": \"test/*\",\n      \"rules\": {\n        \"@typescript-eslint/no-empty-function\": \"off\"\n      },\n      \"globals\": {\n        \"chai\": false,\n        \"expect\": false\n      },\n      \"env\": {\n        \"mocha\": true\n      }\n    },\n    {\n      \"files\": \"*.cjs\",\n      \"rules\": {\n        \"import/no-commonjs\": \"off\"\n      },\n      \"env\": {\n        \"node\": true\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".github/workflows/lighthouse.yml",
    "content": "name: Lighthouse\npermissions:\n  contents: read\n\non: [pull_request]\n\njobs:\n  lhci:\n    name: Lighthouse\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout the project\n        uses: actions/checkout@v3\n\n      - name: Use Node.js 24.x (LTS)\n        uses: actions/setup-node@v3\n        with:\n          node-version: 24.x\n          cache: 'npm'\n      - run: npm ci\n\n      - name: Use Ruby 2.7.3\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: '2.7.3'\n          bundler-cache: true\n          working-directory: docs\n\n      - name: Build docs\n        run: npm run build:docs\n        env:\n          JEKYLL_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Run Lighthouse CI\n        run: npx @lhci/cli@0.9.x autorun\n        env:\n          JEKYLL_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          LHCI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/nodejs.yml",
    "content": "name: Build\npermissions:\n  contents: read\n\non:\n  pull_request:\n  push:\n\njobs:\n  test-node:\n    name: Test on Node.js\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout the project\n      uses: actions/checkout@v3\n    - name: Use Node.js 24.x (LTS)\n      uses: actions/setup-node@v3\n      with:\n        node-version: 24.x\n        cache: 'npm'\n    - run: npm ci\n    - name: Lint Codebase\n      run: npm run lint\n    - name: Run Node.js Tests\n      run: npm run test\n    - name: Check Bundle Size\n      run: npm run size\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish\n\non:\n  release:\n    types: [created]\n\npermissions:\n  contents: read\n  id-token: write # for provenance and publish access\n\njobs:\n  publish-npm:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout the project\n        uses: actions/checkout@v3\n      - name: Use Node.js 24.x (LTS)\n        uses: actions/setup-node@v3\n        with:\n          node-version: 24.x\n          registry-url: https://registry.npmjs.org/\n          cache: npm\n      - run: npm ci\n      - run: npm test\n      - run: npm version ${TAG_NAME} --git-tag-version=false\n        env:\n          TAG_NAME: ${{ github.event.release.tag_name }}\n      - run: npm publish --provenance\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n_site\n*.tsbuildinfo\nlib/\n.jekyll-cache\n.lighthouseci\ncoverage\n"
  },
  {
    "path": ".nvmrc",
    "content": "13.11.0\n"
  },
  {
    "path": "CODEOWNERS",
    "content": "* @github/primer-reviewers @koddsson\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 opensource@github.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[fork]: https://github.com/github/catalyst/fork\n[pr]: https://github.com/github/catalyst/compare\n[style]: https://github.com/styleguide/ruby\n[code-of-conduct]: CODE_OF_CONDUCT.md\n\nHi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.\n\nContributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE.md).\n\nPlease note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.\n\n## Submitting a pull request\n\n0. [Fork][fork] and clone the repository\n0. Configure and install the dependencies: `npm i`\n0. Make sure the tests pass on your machine: `npm t`\n0. Create a new branch: `git checkout -b my-branch-name`\n0. Make your change, add tests, and make sure the tests still pass\n0. Push to your fork and [submit a pull request][pr]\n0. Pat your self on the back and wait for your pull request to be reviewed and merged.\n\nHere are a few things you can do that will increase the likelihood of your pull request being accepted:\n\n- Follow the [style guide][style].\n- Write tests.\n- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.\n- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).\n\n## Resources\n\n- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)\n- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)\n- [GitHub Help](https://help.github.com)\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 GitHub\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Catalyst\n\nCatalyst is a set of patterns and techniques for developing components within a complex application. At its core, Catalyst simply provides a small library of functions to make developing [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) easier.\n\nFor more see the [Catalyst Website](https://github.github.io/catalyst/) which includes a [Guide To using Catalyst](https://github.github.io/catalyst/guide/introduction).\n"
  },
  {
    "path": "SECURITY.md",
    "content": "If you discover a security issue in this repository, please submit it through the [GitHub Security Bug Bounty](https://hackerone.com/github).\n"
  },
  {
    "path": "docs/404.html",
    "content": "---\nlayout: default\n---\n\n<style type=\"text/css\" media=\"screen\">\n  .container {\n    margin: 10px auto;\n    max-width: 600px;\n    text-align: center;\n  }\n  h1 {\n    margin: 30px 0;\n    font-size: 4em;\n    line-height: 1;\n    letter-spacing: -1px;\n  }\n</style>\n\n<div class=\"container\">\n  <h1>404</h1>\n\n  <p><strong>Page not found :(</strong></p>\n  <p>The requested page could not be found.</p>\n</div>\n"
  },
  {
    "path": "docs/Gemfile",
    "content": "# frozen_string_literal: true\n\nsource 'https://rubygems.org'\n\ngem 'jekyll'\n\ngroup :jekyll_plugins do\n  gem 'jekyll-commonmark-ghpages'\n  gem 'jekyll-github-metadata'\n  gem 'jekyll-gzip'\nend\n"
  },
  {
    "path": "docs/_config.yml",
    "content": "title: Catalyst\n\nmarkdown: CommonMarkGhPages\n\ncommonmark:\n  extensions: ['autolink', 'table']\n\npermalink: pretty\n\nexclude:\n  - Gemfile\n  - Gemfile.lock\n  - node_modules\n  - vendor\n\ncollections:\n  guide:\n    output: true\n\ndefaults:\n  - scope:\n      type: guide\n    values:\n      layout: guide\n\nrepository: github/catalyst\n\nplugins:\n  - 'jekyll-github-metadata'\n  - 'jekyll-gzip'\n"
  },
  {
    "path": "docs/_guide/abilities.md",
    "content": "---\nversion: 2\nchapter: 4\ntitle: Abilities\nsubtitle: Abilities\npermalink: /guide-v2/abilities\n---\n\nUnder the hood Catalyst's controller decorator is comprised of a handful of separate \"abilities\". An \"ability\" is essentially a mixin or perhaps \"higher order class\". An ability takes a class and returns an extended class that adds additional behaviours. By convention all abilities exported by Catalyst are suffixed with `able` which we think is a nice way to denote that something is an ability and should be used as such.\n\n### Using Abilities\n\nAbilities are fundementally just class decorators, and so can be used just like the `@controller` decorator. For example to add only the `actionable` decorator (which automatically binds events based on `data-action` attributes):\n\n```typescript\nimport {actionable} from '@github/catalyst'\n\n@actionable\nclass HelloWorld extends HTMLElement {\n}\n```\n\n### Using Marks\n\nAbilities also come with complementary field decorators which we call \"marks\" (we give them a distinctive name because they're a more restrictive subset of field decorators). Marks annotate fields which abilities can then extend with custom logic, both [Targets]({{ site.baseurl }}/guide/targets) and [Attrs]({{ site.baseurl }}/guide/attrs) are abilities that use marks. The `targetable` ability includes `target` & `targets` marks, and the `attrable` ability includes the `attr` mark. Marks decorate individual fields, like so:\n\n```typescript\nimport {targetable, target, targets} from '@github/catalyst'\n\n@targetable\nclass HelloWorldElement extends HTMLElement {\n    @target name\n    @targets people\n}\n```\n\nMarks _can_ decorate over fields, get/set functions, or class methods - but individual marks can set their own validation logic, for example enforcing a naming pattern or disallowing application on methods.\n\n### Built-In Abilities\n\nCatalyst ships with a set of built in abilities. The `@controller` decorator applies the following built-in abilities:\n\n- `controllable` - the base ability which other abilities require for functionality.\n- `targetable` - the ability to define `@target` and `@targets` properties. See [Targets]({{ site.baseurl }}/guide/targets) for more.\n- `actionable` - the ability to automatically bind events based on `data-action` attributes. See [Actions]({{ site.baseurl }}/guide/actions) for more.\n- `attrable` - the ability to define `@attr`s. See [Attrs]({{ site.baseurl }}/guide/attrs) for more.\n\nThe `@controller` decorator also applies the `@register` decorator which automatically registers the element in the Custom Element registry, however this decorator isn't an \"ability\".\n\nThe following abilities are shipped with Catalyst but require manually applying as they aren't considered critical functionality:\n\n - `providable` - the ability to define `provider` and `consumer` properties. See [Providable]({{ site.baseurl }}/guide/providable) for more.\n\nIn addition to the provided abilities, Catalyst provides all of the tooling to create your own custom abilities. Take a look at the [Create Ability]({{ site.baseurl }}/guide/create-ability) documentation for more!\n"
  },
  {
    "path": "docs/_guide/actions-2.md",
    "content": "---\nversion: 2\nchapter: 6\ntitle: Actionable\nsubtitle: Binding Events\npermalink: /guide-v2/actions\n---\n\nCatalyst Components automatically bind actions upon instantiation. Automatically as part of the `connectedCallback`, a component will search for any children with the `data-action` attribute, and bind events based on the value of this attribute. Any _public method_ on a Controller can be bound to via `data-action`.\n\n{% capture callout %}\nRemember! Actions are _automatically_ bound using the `@controller` decorator. There's no extra JavaScript code needed.\n{% endcapture %}{% include callout.md %}\n\n### Example\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n<!-- annotations\ndata-action \"click.*\": Will call `greetSomeone()` when clicked\n-->\n\n```html\n<hello-world>\n  <input\n    data-target=\"hello-world.name\"\n    type=\"text\"\n  >\n\n  <button\n    data-action=\"click:hello-world#greetSomeone\">\n    Greet Someone\n  </button>\n\n  <span\n    data-target=\"hello-world.output\">\n  </span>\n</hello-world>\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n<!-- annotations\ngreetSomeone: All public methods can be called with `data-action`\n-->\n\n```js\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target name: HTMLElement\n  @target output: HTMLElement\n\n  greetSomeone() {\n    this.output.textContent =\n      `Hello, ${this.name.value}!`\n  }\n}\n```\n\n  </div>\n</div>\n\n### Actions Syntax\n\nThe actions syntax follows a pattern of `event:controller#method`.\n\n - `event` must be the name of a [_DOM Event_](https://developer.mozilla.org/en-US/docs/Web/Events), e.g. `click`.\n - `controller` must be the name of a controller ascendant to the element.\n - `method` (optional) must be a _public_ _method_ attached to a controller's prototype. Static methods will not work.\n\nIf method is not supplied, it will default to `handleEvent`.\n\nSome examples of Actions Syntax:\n\n- `click:my-element#foo` -> `click` events will call `foo` on `my-element` elements.\n- `submit:my-element#foo` -> `submit` events will call `foo` on `my-element` elements.\n- `click:user-list` -> `click` events will call `handleEvent` on `user-list` elements.\n- `click:user-list#` -> `click` events will call `handleEvent` on `user-list` elements.\n- `click:top-header-user-profile#` -> `click` events will call `handleEvent` on `top-header-user-profile` elements.\n- `nav:keydown:user-list` -> `navigation:keydown` events will call `handleEvent` on `user-list` elements.\n\n### Multiple Actions\n\nMultiple actions can be bound to multiple events, methods, and controllers. For example:\n\n<!-- annotations\ndata-action: Fires all of these methods depending on the event\n-->\n\n```html\n<analytics-tracking>\n  <hello-world>\n    <input\n      data-target=\"hello-world.name\"\n      data-action=\"\n        input:hello-world#validate\n        blur:hello-world#validate\n        focus:analytics-tracking#focus\n      \"\n      type=\"text\"\n    >\n\n    <button\n      data-action=\"\n        click:hello-world#greetSomeone\n        click:analytics-tracking#click\n        mouseover:analytics-tracking#hover\n      \"\n    >\n      Greet Someone\n    </button>\n  </hello-world>\n</analytics-tracking>\n```\n\n### Custom Events\n\nA Controller may emit custom events, which may be listened to by other Controllers using the same Actions Syntax. There is no extra syntax needed for this. For example a `lazy-loader` Controller might dispatch a `loaded` event, once its contents are loaded, and other controllers can listen to this event:\n\n<!-- annotations\ndata-action \"loaded: Calls enable() on the `loaded` custom event\n-->\n\n```html\n<hover-card disabled>\n  <lazy-loader data-url=\"/user/1\" data-action=\"loaded:hover-card#enable\">\n    <loading-spinner>\n  </lazy-loader>\n</hover-card>\n```\n\n<!-- annotations\nthis . dispatchEvent . new CustomEvent . . loaded . . : Dispatches custom \"loaded\" event\nenable: All public methods can be called with `data-action`\n-->\n\n```js\nimport {controller} from '@github/catalyst'\n\n@controller\nclass LazyLoader extends HTMLElement {\n\n  connectedCallback() {\n    this.innerHTML = await (await fetch(this.dataset.url)).text()\n    this.dispatchEvent(new CustomEvent('loaded'))\n  }\n\n}\n\n@controller\nclass HoverCard extends HTMLElement {\n\n  enable() {\n    this.disabled = false\n  }\n\n}\n```\n\n### Targets and \"ShadowRoots\"\n\nCustom elements can create encapsulated DOM trees known as \"Shadow\" DOM. Catalyst actions support Shadow DOM by traversing the `shadowRoot`, if present, and also automatically watching shadowRoots for changes; auto-binding new elements as they are added.\n\n### What about without Decorators?\n\nIf you're using decorators, then the `@controller` decorator automatically handles binding of actions to a Controller.\n\nIf you're not using decorators, then you'll need to call `bind(this)` somewhere inside of `connectedCallback()`.\n\n```js\nimport {bind} from '@github/catalyst'\n\nclass HelloWorldElement extends HTMLElement {\n  connectedCallback() {\n    bind(this)\n  }\n}\n```\n\n### Binding dynamically added actions\n\nCatalyst automatically listens for elements that are dynamically injected into the DOM, and will bind any element's `data-action` attributes. It does this by calling `listenForBind(controller.ownerDocument)`. If for some reason you need to observe other documents (such as mutations within an iframe), then you can call the `listenForBind` manually, passing a `Node` to listen to DOM mutations on.\n\n```js\nimport {listenForBind} from '@github/catalyst'\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target iframe: HTMLIFrameElement\n\n  connectedCallback() {\n    // listenForBind(this.ownerDocument) is automatically called.\n\n    listenForBind(this.iframe.document.body)\n  }\n}\n```\n"
  },
  {
    "path": "docs/_guide/actions.md",
    "content": "---\nversion: 1\nchapter: 5\ntitle: Actions\nsubtitle: Binding Events\n---\n\nCatalyst Components automatically bind actions upon instantiation. Automatically as part of the `connectedCallback`, a component will search for any children with the `data-action` attribute, and bind events based on the value of this attribute. Any _public method_ on a Controller can be bound to via `data-action`.\n\n{% capture callout %}\nRemember! Actions are _automatically_ bound using the `@controller` decorator. There's no extra JavaScript code needed.\n{% endcapture %}{% include callout.md %}\n\n### Example\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n<!-- annotations\ndata-action \"click.*\": Will call `greetSomeone()` when clicked\n-->\n\n```html\n<hello-world>\n  <input\n    data-target=\"hello-world.name\"\n    type=\"text\"\n  >\n\n  <button\n    data-action=\"click:hello-world#greetSomeone\">\n    Greet Someone\n  </button>\n\n  <span\n    data-target=\"hello-world.output\">\n  </span>\n</hello-world>\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n<!-- annotations\ngreetSomeone: All public methods can be called with `data-action`\n-->\n\n```js\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target name: HTMLElement\n  @target output: HTMLElement\n\n  greetSomeone() {\n    this.output.textContent =\n      `Hello, ${this.name.value}!`\n  }\n}\n```\n\n  </div>\n</div>\n\n### Actions Syntax\n\nThe actions syntax follows a pattern of `event:controller#method`.\n\n - `event` must be the name of a [_DOM Event_](https://developer.mozilla.org/en-US/docs/Web/Events), e.g. `click`.\n - `:` is the required delimiter between the `event` and `controller`.\n - `controller` must be the name of a controller ascendant to the element.\n - `#` is the required delimieter between the `controller` and `method`.\n - `method` (optional) must be a _public_ _method_ attached to a controller's prototype. Static methods will not work.\n\nIf method is not supplied, it will default to `handleEvent`.\n\nSome examples of Actions Syntax:\n\n- `click:my-element#foo` -> `click` events will call `foo` on `my-element` elements.\n- `submit:my-element#foo` -> `submit` events will call `foo` on `my-element` elements.\n- `click:user-list` -> `click` events will call `handleEvent` on `user-list` elements.\n- `click:user-list#` -> `click` events will call `handleEvent` on `user-list` elements.\n- `click:top-header-user-profile#` -> `click` events will call `handleEvent` on `top-header-user-profile` elements.\n- `nav:keydown:user-list` -> `navigation:keydown` events will call `handleEvent` on `user-list` elements.\n\n### Multiple Actions\n\nMultiple actions can be bound to multiple events, methods, and controllers. For example:\n\n<!-- annotations\ndata-action: Fires all of these methods depending on the event\n-->\n\n```html\n<analytics-tracking>\n  <hello-world>\n    <input\n      data-target=\"hello-world.name\"\n      data-action=\"\n        input:hello-world#validate\n        blur:hello-world#validate\n        focus:analytics-tracking#focus\n      \"\n      type=\"text\"\n    >\n\n    <button\n      data-action=\"\n        click:hello-world#greetSomeone\n        click:analytics-tracking#click\n        mouseover:analytics-tracking#hover\n      \"\n    >\n      Greet Someone\n    </button>\n  </hello-world>\n</analytics-tracking>\n```\n\n### Custom Events\n\nA Controller may emit custom events, which may be listened to by other Controllers using the same Actions Syntax. There is no extra syntax needed for this. For example a `lazy-loader` Controller might dispatch a `loaded` event, once its contents are loaded, and other controllers can listen to this event:\n\n<!-- annotations\ndata-action \"loaded: Calls enable() on the `loaded` custom event\n-->\n\n```html\n<hover-card disabled>\n  <lazy-loader data-url=\"/user/1\" data-action=\"loaded:hover-card#enable\">\n    <loading-spinner>\n  </lazy-loader>\n</hover-card>\n```\n\n<!-- annotations\nthis . dispatchEvent . new CustomEvent . . loaded . . : Dispatches custom \"loaded\" event\nenable: All public methods can be called with `data-action`\n-->\n\n```js\nimport {controller} from '@github/catalyst'\n\n@controller\nclass LazyLoader extends HTMLElement {\n\n  connectedCallback() {\n    this.innerHTML = await (await fetch(this.dataset.url)).text()\n    this.dispatchEvent(new CustomEvent('loaded'))\n  }\n\n}\n\n@controller\nclass HoverCard extends HTMLElement {\n\n  enable() {\n    this.disabled = false\n  }\n\n}\n```\n\n### Targets and \"ShadowRoots\"\n\nCustom elements can create encapsulated DOM trees known as \"Shadow\" DOM. Catalyst actions support Shadow DOM by traversing the `shadowRoot`, if present, and also automatically watching shadowRoots for changes; auto-binding new elements as they are added.\n\n### What about without Decorators?\n\nIf you're using decorators, then the `@controller` decorator automatically handles binding of actions to a Controller.\n\nIf you're not using decorators, then you'll need to call `bind(this)` somewhere inside of `connectedCallback()`.\n\n```js\nimport {bind} from '@github/catalyst'\n\nclass HelloWorldElement extends HTMLElement {\n  connectedCallback() {\n    bind(this)\n  }\n}\n```\n\n### Binding dynamically added actions\n\nCatalyst automatically listens for elements that are dynamically injected into the DOM, and will bind any element's `data-action` attributes. It does this by calling `listenForBind(controller.ownerDocument)`. If for some reason you need to observe other documents (such as mutations within an iframe), then you can call the `listenForBind` manually, passing a `Node` to listen to DOM mutations on.\n\n```js\nimport {listenForBind} from '@github/catalyst'\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target iframe: HTMLIFrameElement\n\n  connectedCallback() {\n    // listenForBind(this.ownerDocument) is automatically called.\n\n    listenForBind(this.iframe.document.body)\n  }\n}\n```\n"
  },
  {
    "path": "docs/_guide/anti-patterns-2.md",
    "content": "---\nversion: 2\nchapter: 15\ntitle: Anti Patterns\nsubtitle: Things to avoid building components\npermalink: /guide-v2/anti-patterns\n---\n\n{% capture octx %}<svg class=\"octicon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\"><path fill-rule=\"evenodd\" d=\"M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm8.036-4.024a.75.75 0 00-1.06 1.06L10.939 12l-2.963 2.963a.75.75 0 101.06 1.06L12 13.06l2.963 2.964a.75.75 0 001.061-1.06L13.061 12l2.963-2.964a.75.75 0 10-1.06-1.06L12 10.939 9.036 7.976z\"></path></svg>{% endcapture %}\n{% capture octick %}<svg class=\"octicon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\"><path fill-rule=\"evenodd\" d=\"M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z\"></path></svg>{% endcapture %}\n{% capture discouraged %}<h4 class=\"text-red\">{{ octx }} Discouraged</h4>{% endcapture %}\n{% capture encouraged %}<h4 class=\"text-green\">{{ octick }} Encouraged</h4>{% endcapture %}\n\nHere are a few common anti-patterns which we've discovered as developers have used Catalyst. We consider these anti-patterns as they're best avoided, because of surprising edge-cases, or simply because there are easier ways to achieve the same goals.\n\n### Avoid doing any initialisation in the constructor\n\nWith conventional classes, it is expected that initialisation will be done in the `constructor()` method. Custom Elements are slightly different, because the `constructor` is called _before_ the element has been put into the Document, which means any initialisation that expects to be connected to a DOM will fail. \n\n{{ discouraged }}\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  constructor() {\n    // This will fire before DOM is connected, so will never bubble!\n    this.dispatchEvent(new CustomEvent('loaded'))\n  }\n}\n```\n\n{{ encouraged }}\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  connectedCallback() {\n    // This will fire _after_ DOM is connected, so will bubble up as expected\n    this.dispatchEvent(new CustomEvent('loaded'))\n  }\n}\n```\n\n\n### Avoid interacting with parents, use Events where possible\n\nSometimes it's necessary to let ancestors know about the state of a child element, for example when an element loads or needs the parent to change somehow. Sometimes it can be tempting to use methods like `this.closest()` to get a reference to the parent element and interact with it directly, but this creates a fragile coupling to elements and is best avoided. Events can used here, instead:\n\n{{ discouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserSettingsElement extends HTMLElement {\n  loading() {\n    // While this is loading we need to disable\n    // the whole User if `user-profile` ever\n    // changes, this code will break!\n    this\n      .closest('user-profile')\n      .disable()\n  }\n}\n```\n\n  </div><div class=\"ml-4\">\n\n```html\n<user-profile>\n  <user-settings></user-settings>\n</user-profile>\n```\n\n  </div>\n</div>\n\nInstead of interacting with the parent's API directly in JS, you can use `Events` which can be listened to with `data-action`, this moves any coupling into the HTML which already has the association, and so subsequent refactors will have far less risk of breaking the code:\n\n{{ encouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserSettingsElement extends HTMLElement {\n  loading() {\n    this.dispatchEvent(\n      new CustomEvent('loading')\n    )\n  }\n}\n```\n\n  </div><div class=\"ml-4\">\n\n```html\n<user-profile>\n  <user-settings\n    data-action=\"loading:user-profile#disable\">\n  </user-settings>\n</user-profile>\n```\n\n  </div>\n</div>\n\n### Avoid shadowing method names\n\nWhen naming a method, you should avoid naming it something that already exists on the `HTMLElement` prototype; as doing so can lead to surprising behaviors. Test out the form below to see what method names are allowed or not:\n\n<form>\n  <label>\n    <h4>I want my method to be called...</h4>\n    <input class=\"js-methodname-shadow-test mb-4\">\n  </label>\n  <div hidden class=\"js-methodname-shadow-bad-input text-red\">\n    {{ octx }} This name would shadow <code></code>, you'll need to pick a different name\n  </div>\n  <div hidden class=\"js-methodname-shadow-warn-input text-orange-light\">\n    {{ octx }} While this name is allowed, it's not ideal because <span></span>. You should consider a different name.\n  </div>\n  <div hidden class=\"js-methodname-shadow-good-input text-green\">\n    {{ octick }} This is a good name for a method!\n  </div>\n  <script>\n    const warnings = {\n      'new': 'it has a special meaning in JS',\n      'super': 'it has a special meaning in JS',\n      'prototype': 'it has a special meaning in JS',\n      'requestSubmit': 'it is a proposed new feature',\n    }\n    document.querySelector('.js-methodname-shadow-test').addEventListener('input', () => {\n      const name = event.target.value\n      const goodEl = document.querySelector('.js-methodname-shadow-good-input')\n      const badEl = document.querySelector('.js-methodname-shadow-bad-input')\n      const warnEl = document.querySelector('.js-methodname-shadow-warn-input')\n      if (name === '') {\n        goodEl.hidden = true\n        return\n      }\n      let warning = warnings[name]\n      if (name !== name.toLowerCase() && name.toLowerCase() in HTMLElement.prototype) {\n        warning = `it is too similar to \\`${name.toLowerCase()}\\` which already exists`\n      } else if (name.startsWith('on') && !(name in HTMLElement.prototype)) {\n        warning = 'starting with `on` suggests a coupling between the event and the method (see below)'\n      }\n      goodEl.hidden = warning || (name in HTMLElement.prototype)\n      warnEl.hidden = !warning\n      badEl.hidden = warning || !(name in HTMLElement.prototype)\n      if (warning) {\n        warnEl.querySelector('span').textContent = warning\n      } else if (name in HTMLElement.prototype) {\n        let proto = HTMLElement.prototype\n        while(proto !== null) {\n          if (proto.hasOwnProperty(name)) break\n          proto = Object.getPrototypeOf(proto)\n        }\n        badEl.querySelector('code').textContent = `${proto.constructor.name}.prototype.${name}`\n      }\n    })\n  </script>\n</form>\n\n### Avoid naming methods after events, e.g. `onClick`\n\nWhen you have a method which is only called as an event, it is tempting to name that method based off of the event, e.g. `onClick`, `onInputFocus`, and so on. This name implies a coupling between the event and method, which later refactorings may break. Also names like `onClick` are very close to `onclick` which is already [part of the Element's API](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick). Instead we recommend naming the method after what it does, not how it is called, for example `resetForm`:\n\n{{ discouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```js\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserLoginElement extends HTMLElement {\n\n  // `onClick` is not clear\n  onClick() {\n    // Log the user in\n  }\n}\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n```html\n<user-login>\n  <!-- ... -->\n  <button\n    data-action=\"click:user-login#onClick\">\n    <!-- `onClick` is not clear -->\n    Log In\n  </button>\n</user-login>\n```\n\n  </div>\n</div>\n\n{{ encouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```js\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserLoginElement extends HTMLElement {\n\n  login() {\n    // Log the user in\n  }\n}\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n```html\n<user-login>\n  <!-- ... -->\n  <button\n    data-action=\"click:user-login#login\">\n    Log In\n  </button>\n</user-login>\n```\n\n  </div>\n</div>\n\n### Avoid querying against your element, use `@target` or `@targets`\n\nWe find it very common for developers to return to habits and use `querySelector[All]` when needing to get elements. The `@target` and `@targets` decorators were designed to simplify `querySelector[All]` and avoid certain bugs with them (such as nesting issues, and unnecessary coupling) so it's a good idea to use them as much as possible:\n\n{{ discouraged }}\n\n```typescript\nclass UserListElement extends HTMLElement {\n  showAdmins() {\n    // Just need to get admins here...\n    for (const user of this.querySelector('[data-is-admin]')) {\n      user.hidden = false\n    }\n  }\n}\n```\n\n{{ encouraged }}\n\n```typescript\nclass UserList {\n  @targets admins: HTMLElement[]\n\n  showAdmins() {\n    // Just need to get admins here...\n    for (const user of this.admins) {\n      user.hidden = false\n    }\n  }\n}\n```\n\n\n### Avoid filtering `@targets`, use another `@target` or `@targets`\n\n\nSometimes you might need to get a subset of elements from a `@targets` selector. When doing this, simply use another `@target` or `@targets` attribute, it's okay to have many of these! Adding getters which simply return a `@targets` subset has various drawbacks which make it an anti pattern.\n\nFor example let's say we have a list of filter checkboxes and checking the \"all\" checkbox unchecks all other checkboxes:\n\n{{ discouraged }}\n\n```typescript\n@controller\nclass UserFilter {\n  @targets filters: HTMLInputElement[]\n\n  get allFilter() {\n    return this.filters.find(el => el.matches('[data-filter=\"all\"]'))\n  }\n\n  filter(event: Event) {\n    if (event.target === this.allFilter) {\n      for(const filter of this.filters) {\n        if (filter !== this.allFilter) filter.checked = false\n      }\n    }\n    // ...\n  }\n\n}\n```\n\n```html\n<user-filter>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"all\">Show all</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"new\">New Users</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"admin\">Admins</label>\n  <!-- ... --->\n</user-filter>\n```\n\nWhile this works well, it could be more easily solved with targets:\n\n{{ encouraged }}\n\n```typescript\n@controller\nclass UserFilter {\n  @targets filters: HTMLInputElement[]\n  @target allFilter: HTMLInputElement\n\n  filter(event: Event) {\n    if (event.target === this.allFilter) {\n      for (const filter of this.filters) {\n        if (filter !== this.allFilter) filter.checked = false\n      }\n    }\n    // ...\n  }\n\n}\n```\n\n```html\n<user-filter>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-target=\"user-filter.allFilter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"all\">Show all</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"new\">New Users</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"admin\">Admins</label>\n  <!-- ... --->\n</user-filter>\n```\n"
  },
  {
    "path": "docs/_guide/anti-patterns.md",
    "content": "---\nversion: 1\nchapter: 11\ntitle: Anti Patterns\nsubtitle: Things to avoid building components\n---\n\n{% capture octx %}<svg class=\"octicon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\"><path fill-rule=\"evenodd\" d=\"M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm8.036-4.024a.75.75 0 00-1.06 1.06L10.939 12l-2.963 2.963a.75.75 0 101.06 1.06L12 13.06l2.963 2.964a.75.75 0 001.061-1.06L13.061 12l2.963-2.964a.75.75 0 10-1.06-1.06L12 10.939 9.036 7.976z\"></path></svg>{% endcapture %}\n{% capture octick %}<svg class=\"octicon\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\"><path fill-rule=\"evenodd\" d=\"M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12zm16.28-2.72a.75.75 0 00-1.06-1.06l-5.97 5.97-2.47-2.47a.75.75 0 00-1.06 1.06l3 3a.75.75 0 001.06 0l6.5-6.5z\"></path></svg>{% endcapture %}\n{% capture discouraged %}<h4 class=\"text-red\">{{ octx }} Discouraged</h4>{% endcapture %}\n{% capture encouraged %}<h4 class=\"text-green\">{{ octick }} Encouraged</h4>{% endcapture %}\n\nHere are a few common anti-patterns which we've discovered as developers have used Catalyst. We consider these anti-patterns as they're best avoided, because of surprising edge-cases, or simply because there are easier ways to achieve the same goals.\n\n### Avoid doing any initialisation in the constructor\n\nWith conventional classes, it is expected that initialisation will be done in the `constructor()` method. Custom Elements are slightly different, because the `constructor` is called _before_ the element has been put into the Document, which means any initialisation that expects to be connected to a DOM will fail. \n\n{{ discouraged }}\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  constructor() {\n    // This will fire before DOM is connected, so will never bubble!\n    this.dispatchEvent(new CustomEvent('loaded'))\n  }\n}\n```\n\n{{ encouraged }}\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  connectedCallback() {\n    // This will fire _after_ DOM is connected, so will bubble up as expected\n    this.dispatchEvent(new CustomEvent('loaded'))\n  }\n}\n```\n\n\n### Avoid interacting with parents, use Events where possible\n\nSometimes it's necessary to let ancestors know about the state of a child element, for example when an element loads or needs the parent to change somehow. Sometimes it can be tempting to use methods like `this.closest()` to get a reference to the parent element and interact with it directly, but this creates a fragile coupling to elements and is best avoided. Events can used here, instead:\n\n{{ discouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserSettingsElement extends HTMLElement {\n  loading() {\n    // While this is loading we need to disable\n    // the whole User if `user-profile` ever\n    // changes, this code will break!\n    this\n      .closest('user-profile')\n      .disable()\n  }\n}\n```\n\n  </div><div class=\"ml-4\">\n\n```html\n<user-profile>\n  <user-settings></user-settings>\n</user-profile>\n```\n\n  </div>\n</div>\n\nInstead of interacting with the parent's API directly in JS, you can use `Events` which can be listened to with `data-action`, this moves any coupling into the HTML which already has the association, and so subsequent refactors will have far less risk of breaking the code:\n\n{{ encouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```typescript\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserSettingsElement extends HTMLElement {\n  loading() {\n    this.dispatchEvent(\n      new CustomEvent('loading')\n    )\n  }\n}\n```\n\n  </div><div class=\"ml-4\">\n\n```html\n<user-profile>\n  <user-settings\n    data-action=\"loading:user-profile#disable\">\n  </user-settings>\n</user-profile>\n```\n\n  </div>\n</div>\n\n### Avoid shadowing method names\n\nWhen naming a method, you should avoid naming it something that already exists on the `HTMLElement` prototype; as doing so can lead to surprising behaviors. Test out the form below to see what method names are allowed or not:\n\n<form>\n  <label>\n    <h4>I want my method to be called...</h4>\n    <input class=\"js-methodname-shadow-test mb-4\">\n  </label>\n  <div hidden class=\"js-methodname-shadow-bad-input text-red\">\n    {{ octx }} This name would shadow <code></code>, you'll need to pick a different name\n  </div>\n  <div hidden class=\"js-methodname-shadow-warn-input text-orange-light\">\n    {{ octx }} While this name is allowed, it's not ideal because <span></span>. You should consider a different name.\n  </div>\n  <div hidden class=\"js-methodname-shadow-good-input text-green\">\n    {{ octick }} This is a good name for a method!\n  </div>\n  <script>\n    const warnings = {\n      'new': 'it has a special meaning in JS',\n      'super': 'it has a special meaning in JS',\n      'prototype': 'it has a special meaning in JS',\n      'requestSubmit': 'it is a proposed new feature',\n    }\n    document.querySelector('.js-methodname-shadow-test').addEventListener('input', () => {\n      const name = event.target.value\n      const goodEl = document.querySelector('.js-methodname-shadow-good-input')\n      const badEl = document.querySelector('.js-methodname-shadow-bad-input')\n      const warnEl = document.querySelector('.js-methodname-shadow-warn-input')\n      if (name === '') {\n        goodEl.hidden = true\n        return\n      }\n      let warning = warnings[name]\n      if (name !== name.toLowerCase() && name.toLowerCase() in HTMLElement.prototype) {\n        warning = `it is too similar to \\`${name.toLowerCase()}\\` which already exists`\n      } else if (name.startsWith('on') && !(name in HTMLElement.prototype)) {\n        warning = 'starting with `on` suggests a coupling between the event and the method (see below)'\n      }\n      goodEl.hidden = warning || (name in HTMLElement.prototype)\n      warnEl.hidden = !warning\n      badEl.hidden = warning || !(name in HTMLElement.prototype)\n      if (warning) {\n        warnEl.querySelector('span').textContent = warning\n      } else if (name in HTMLElement.prototype) {\n        let proto = HTMLElement.prototype\n        while(proto !== null) {\n          if (proto.hasOwnProperty(name)) break\n          proto = Object.getPrototypeOf(proto)\n        }\n        badEl.querySelector('code').textContent = `${proto.constructor.name}.prototype.${name}`\n      }\n    })\n  </script>\n</form>\n\n### Avoid naming methods after events, e.g. `onClick`\n\nWhen you have a method which is only called as an event, it is tempting to name that method based off of the event, e.g. `onClick`, `onInputFocus`, and so on. This name implies a coupling between the event and method, which later refactorings may break. Also names like `onClick` are very close to `onclick` which is already [part of the Element's API](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick). Instead we recommend naming the method after what it does, not how it is called, for example `resetForm`:\n\n{{ discouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```js\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserLoginElement extends HTMLElement {\n\n  // `onClick` is not clear\n  onClick() {\n    // Log the user in\n  }\n}\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n```html\n<user-login>\n  <!-- ... -->\n  <button\n    data-action=\"click:user-login#onClick\">\n    <!-- `onClick` is not clear -->\n    Log In\n  </button>\n</user-login>\n```\n\n  </div>\n</div>\n\n{{ encouraged }}\n\n<div class=\"d-flex my-4\">\n  <div class=\"\">\n\n```js\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass UserLoginElement extends HTMLElement {\n\n  login() {\n    // Log the user in\n  }\n}\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n```html\n<user-login>\n  <!-- ... -->\n  <button\n    data-action=\"click:user-login#login\">\n    Log In\n  </button>\n</user-login>\n```\n\n  </div>\n</div>\n\n### Avoid querying against your element, use `@target` or `@targets`\n\nWe find it very common for developers to return to habits and use `querySelector[All]` when needing to get elements. The `@target` and `@targets` decorators were designed to simplify `querySelector[All]` and avoid certain bugs with them (such as nesting issues, and unnecessary coupling) so it's a good idea to use them as much as possible:\n\n{{ discouraged }}\n\n```typescript\nclass UserListElement extends HTMLElement {\n  showAdmins() {\n    // Just need to get admins here...\n    for (const user of this.querySelector('[data-is-admin]')) {\n      user.hidden = false\n    }\n  }\n}\n```\n\n{{ encouraged }}\n\n```typescript\nclass UserList {\n  @targets admins: HTMLElement[]\n\n  showAdmins() {\n    // Just need to get admins here...\n    for (const user of this.admins) {\n      user.hidden = false\n    }\n  }\n}\n```\n\n\n### Avoid filtering `@targets`, use another `@target` or `@targets`\n\n\nSometimes you might need to get a subset of elements from a `@targets` selector. When doing this, simply use another `@target` or `@targets` attribute, it's okay to have many of these! Adding getters which simply return a `@targets` subset has various drawbacks which make it an anti pattern.\n\nFor example let's say we have a list of filter checkboxes and checking the \"all\" checkbox unchecks all other checkboxes:\n\n{{ discouraged }}\n\n```typescript\n@controller\nclass UserFilter {\n  @targets filters: HTMLInputElement[]\n\n  get allFilter() {\n    return this.filters.find(el => el.matches('[data-filter=\"all\"]'))\n  }\n\n  filter(event: Event) {\n    if (event.target === this.allFilter) {\n      for(const filter of this.filters) {\n        if (filter !== this.allFilter) filter.checked = false\n      }\n    }\n    // ...\n  }\n\n}\n```\n\n```html\n<user-filter>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"all\">Show all</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"new\">New Users</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"admin\">Admins</label>\n  <!-- ... --->\n</user-filter>\n```\n\nWhile this works well, it could be more easily solved with targets:\n\n{{ encouraged }}\n\n```typescript\n@controller\nclass UserFilter {\n  @targets filters: HTMLInputElement[]\n  @target allFilter: HTMLInputElement\n\n  filter(event: Event) {\n    if (event.target === this.allFilter) {\n      for (const filter of this.filters) {\n        if (filter !== this.allFilter) filter.checked = false\n      }\n    }\n    // ...\n  }\n\n}\n```\n\n```html\n<user-filter>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-target=\"user-filter.allFilter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"all\">Show all</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"new\">New Users</label>\n  <label><input type=\"checkbox\"\n    data-action=\"change:user-filter#filter\"\n    data-targets=\"user-filter.filters\"\n    data-filter=\"admin\">Admins</label>\n  <!-- ... --->\n</user-filter>\n```\n"
  },
  {
    "path": "docs/_guide/attrs-2.md",
    "content": "---\nversion: 2\nchapter: 7\ntitle: Attrable\nsubtitle: Using attributes as configuration\npermalink: /guide-v2/attrs\n---\n\nComponents may sometimes manage state, or configuration. We encourage the use of DOM as state, rather than maintaining a separate state. One way to maintain state in the DOM is via [Attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes).\n\nAs Catalyst elements are really just Web Components, they have the `hasAttribute`, `getAttribute`, `setAttribute`, `toggleAttribute`, and `removeAttribute` set of methods available, as well as [`dataset`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/dataset), but these can be a little tedious to use; requiring null checking code with each call.\n\nCatalyst includes the `@attr` decorator which provides nice syntax sugar to simplify, standardise, and encourage use of attributes. `@attr` has the following benefits over the basic `*Attribute` methods:\n\n - It dasherizes a property name, making it safe for HTML serialization without conflicting with [built-in global attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes). This works the same as the class name, so for example `@attr pathName` will be `path-name` in HTML, `@attr srcURL` will be `src-url` in HTML.\n - An `@attr` property automatically casts based on the initial value - if the initial value is a `string`, `boolean`, or `number` - it will never be `null` or `undefined`. No more null checking!\n - It is automatically synced with the HTML attribute. This means setting the class property will update the HTML attribute, and setting the HTML attribute will update the class property!\n - Assigning a value in the class description will make that value the _default_ value so if the HTML attribute isn't set, or is set but later removed the _default_ value will apply.\n\nThis behaves similarly to existing HTML elements where the class field is synced with the html attribute, for example the `<input>` element's `type` field:\n\n```ts\nconst input = document.createElement('input')\nconsole.assert(input.type === 'text') // default value\nconsole.assert(input.hasAttribute('type') === false) // no attribute to override\ninput.setAttribute('type', 'number')\nconsole.assert(input.type === 'number') // overrides based on attribute\ninput.removeAttribute('type')\nconsole.assert(input.type === 'text') // back to default value\n```\n\n{% capture callout %} \nAn important part of `@attr`s is that they _must_ comprise of two words, so that they get a dash when serialised to HTML. This is intentional, to avoid conflicting with [built-in global attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes).  To see how JavaScript property names convert to HTML dasherized names, try typing the name of an `@attr` below:\n{% endcapture %}{% include callout.md %}\n\n<form>\n  <label>\n    <h4>I want my `@attr` to be named...</h4>\n    <input class=\"js-attr-dasherize-test mb-4\">\n  </label>\n  <div hidden class=\"js-attr-dasherize-bad text-red\">\n    {{ octx }} An attr name must be two words, so that the HTML version includes a dash!\n  </div>\n  <div hidden class=\"js-attr-dasherize-good text-green\">\n    {{ octick }} This will be <code></code> in HTML.\n  </div>\n  <script type=\"module\">\n    import {mustDasherize} from 'https://unpkg.com/@github/catalyst/lib/index.js'\n    document.querySelector('.js-attr-dasherize-test').addEventListener('input', () => {\n      let name = event.target.value\n      const goodEl = document.querySelector('.js-attr-dasherize-good')\n      const badEl = document.querySelector('.js-attr-dasherize-bad')\n      if (name === '') {\n        goodEl.hidden = true\n        badEl.hidden = true\n        return\n      }\n      let pass = true\n      try {\n        name = mustDasherize(name)\n      } catch (e) {\n        pass = false\n      }\n      goodEl.querySelector('code').textContent = name\n      goodEl.hidden = !pass\n      badEl.hidden = pass\n    })\n  </script>\n</form>\n\nTo use the `@attr` decorator, attach it to a class field, and it will get/set the value of the matching dasherized HTML attribute.\n\n### Example\n\n<!-- annotations\nattr fooBar: Maps to get/setAttribute('foo-bar')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr fooBar = 'hello'\n}\n```\n\nThis is somewhat equivalent to:\n\n```js\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  get fooBar(): string {\n    return this.getAttribute('foo-bar') || ''\n  }\n\n  set fooBar(value: string): void {\n    return this.setAttribute('foo-bar', value)\n  }\n\n  connectedCallback() {\n    if (!this.hasAttribute('foo-bar')) this.fooBar = 'Hello'\n  }\n\n}\n```\n\n### Attribute Types\n\nThe _type_ of an attribute is automatically inferred based on the type it is first set to. This means once a value is initially set it cannot change type; if it is set a `string` it will never be anything but a `string`. An attribute can only be one of either a `string`, `number`, or `boolean`. The types have small differences in how they behave in the DOM.\n\nBelow is a handy reference for the small differences, this is all explained in more detail below that. \n\n| Type      | When `get` is called | When `set` is called |\n|:----------|----------------------|:---------------------|\n| `string`  | `getAttribute`       | `setAttribute`       |\n| `number`  | `getAttribute`       | `setAttribute`       |\n| `boolean` | `hasAttribute`       | `toggleAttribute`    |\n\n#### String Attributes\n\nIf an attribute is first set to a `string`, then it can only ever be a `string` during the lifetime of an element. The property will revert to the initial value if the attribute doesn't exist, and trying to set it to something that isn't a string will turn it into one before assignment.\n\n<!-- annotations\nattr foo: Maps to get/setAttribute('foo-bar')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr fooBar = 'Hello'\n\n  connectedCallback() {\n    console.assert(this.fooBar === 'Hello')\n    this.fooBar = 'Goodbye'\n    console.assert(this.fooBar === 'Goodbye'')\n    console.assert(this.getAttribute('foo-bar') === 'Goodbye')\n\n    this.removeAttribute('foo-bar')\n    // If the attribute doesn't exist, it'll output the initial value!\n    console.assert(this.fooBar === 'Hello') \n  }\n}\n```\n\n#### Boolean Attributes\n\nIf an attribute is first set to a boolean, then it can only ever be a boolean during the lifetime of an element. Boolean properties check for _presence_ of an attribute, sort of like how [`required`, `disabled` & `readonly` attributes work on forms](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes#boolean_attributes) The property will return `false` if the attribute doesn't exist, and `true` if it does, regardless of the value. If the property is set to `false` then `removeAttribute` is called, whereas `setAttribute(name, '')` is called when setting to a truthy value.\n\n<!-- annotations\nattr foo: Maps to has/toggleAttribute('data-foo')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr fooBar = false\n\n  connectedCallback() {\n    console.assert(this.hasAttribute('foo-bar') === false)\n    this.fooBar = true\n    console.assert(this.hasAttribute('foo-bar') === true)\n    this.setAttribute('foo-bar', 'this value doesnt matter!')\n    console.assert(this.fooBar === true)\n  }\n}\n```\n\n#### Number Attributes\n\nIf an attribute is first set to a number, then it can only ever be a number during the lifetime of an element. This is sort of like the [`maxlength` attribute on inputs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/maxlength). The property will return the initial value if the attribute doesn't exist, and will be coerced to `Number` if it does - this means it is _possible_ to get back `NaN`. Negative numbers and floats are also valid.\n\n<!-- annotations\nattr foo: Maps to get/setAttribute('foo-bar')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr fooBar = 1\n\n  connectedCallback() {\n    this.fooBar = 2\n    console.assert(this.getAttribute('foo-bar') === '2')\n    this.setAttribute('foo-bar', 'not a number')\n    console.assert(Number.isNaN(this.fooBar))\n    this.fooBar = -3.14\n    console.assert(this.getAttribute('foo-bar') === '-3.14')\n  }\n}\n```\n\n### Default Values\n\nWhen an element gets connected to the DOM, the attr is initialized. During this phase Catalyst will determine if the default value should be applied. The default value is defined in the class property. The basic rules are as such:\n\n - If the class property has a value, that is the _default_\n - When connected, if the element _does not_ have a matching attribute, the _default is_ applied.\n - When connected, if the element _does_ have a matching attribute, the default _is not_ applied, the property will be assigned to the value of the attribute instead.\n\n{% capture callout %}\nRemember! The values defined in the class field are the _default_. They won't be set if the element is created and its attribute set to a custom value!\n{% endcapture %}{% include callout.md %}\n\nThe following example illustrates this behavior:\n\n<!-- annotations\nattr name: Maps to get/setAttribute('data-name')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr dataName = 'World'\n  connectedCallback() {\n    this.textContent = `Hello ${this.dataName}`\n  }\n}\n```\n\n<!-- annotations\ndata-name \".*\": Will set the value of `name`\n-->\n\n```html\n<hello-world></hello-world>\n// This will render `Hello World`\n\n<hello-world data-name=\"Catalyst\"></hello-world>\n// This will render `Hello Catalyst`\n\n<hello-world data-name=\"\"></hello-world>\n// This will render `Hello `\n```\n\n### Advanced usage\n\n#### Determining when an @attr changes value\n\nTo be notified when an `@attr` changes value, you can use the decorator over\n\"setter\" method instead, and the method will be called with the new value\nwhenever it is re-assigned, either through HTML or JavaScript:\n\n```typescript\nimport { controller, attr } from \"@github/catalyst\"\n@controller\nclass HelloWorldElement extends HTMLElement {\n\n  @attr get dataName() {\n    return 'World' // Used to get the intial value\n  }\n  // Called whenever `name` changes\n  set dataName(newValue: string) {\n    this.textContent = `Hello ${newValue}`\n  }\n}\n```\n\n### What about without Decorators?\n\nIf you're not using decorators, then the `@attr` decorator has an escape hatch: You can define a static class field using the `[attr.static]` computed property, as an array of key names. Like so:\n\n```js\nimport {controller, attr} from '@github/catalyst'\n\ncontroller(\nclass HelloWorldElement extends HTMLElement {\n  // Same as @attr fooBar\n  [attr.static] = ['fooBar']\n\n  // Field can still be defined\n  fooBar = 1\n}\n)\n```\n\nThis example is functionally identical to:\n\n```js\nimport {controller, attr} from '@github/catalyst'\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr fooBar = 1\n}\n```\n\n"
  },
  {
    "path": "docs/_guide/attrs.md",
    "content": "---\nversion: 1\nchapter: 6\ntitle: Attrs\nsubtitle: Using attributes as configuration\n---\n\nComponents may sometimes manage state, or configuration. We encourage the use of DOM as state, rather than maintaining a separate state. One way to maintain state in the DOM is via [Attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes).\n\nAs Catalyst elements are really just Web Components, they have the `hasAttribute`, `getAttribute`, `setAttribute`, `toggleAttribute`, and `removeAttribute` set of methods available, as well as [`dataset`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/dataset), but these can be a little tedious to use; requiring null checking code with each call.\n\nCatalyst includes the `@attr` decorator, which provides nice syntax sugar to simplify, standardise, and encourage use of attributes. `@attr` has the following benefits over the basic `*Attribute` methods:\n\n - It maps whatever the property name is to `data-*`, [similar to how `dataset` does](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/dataset#name_conversion), but with more intuitive naming (e.g. `URL` maps to `data-url` not `data--u-r-l`).\n - An `@attr` property is limited to `string`, `boolean`, or `number`, it will never be `null` or `undefined` - instead it has an \"empty\" value. No more null checking!\n - The attribute name is automatically [observed, meaning `attributeChangedCallback` will fire when it changes](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks).\n - Assigning a value in the class description will make that value the _default_ value, so when the element is connected that value is set (unless the element has the attribute defined already).\n\nTo use the `@attr` decorator, attach it to a class field, and it will get/set the value of the matching `data-*` attribute.\n\n### Example\n\n<!-- annotations\nattr foo: Maps to get/setAttribute('datafoo')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr foo = 'hello'\n}\n```\n\nThis is the equivalent to:\n\n```js\nimport { controller } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  get foo(): string {\n    return this.getAttribute('data-foo') || ''\n  }\n\n  set foo(value: string): void {\n    return this.setAttribute('data-foo', value)\n  }\n\n  connectedCallback() {\n    if (!this.hasAttribute('data-foo')) this.foo = 'Hello'\n  }\n\n  static observedAttributes = ['data-foo']\n}\n```\n\n### Attribute Types\n\nThe _type_ of an attribute is automatically inferred based on the type it is first set to. This means once a value is set it cannot change type; if it is set a `string` it will never be anything but a `string`. An attribute can only be one of either a `string`, `number`, or `boolean`. The types have small differences in how they behave in the DOM.\n\nBelow is a handy reference for the small differences, this is all explained in more detail below that. \n\n| Type      | \"Empty\" value | When `get` is called | When `set` is called |\n|:----------|:--------------|----------------------|:---------------------|\n| `string`  | `''`          | `getAttribute`       | `setAttribute`       |\n| `number`  | `0`           | `getAttribute`       | `setAttribute`       |\n| `boolean` | `false`       | `hasAttribute`       | `toggleAttribute`    |\n\n#### String Attributes\n\nIf an attribute is first set to a `string`, then it can only ever be a `string` during the lifetime of an element. The property will return an empty string (`''`) if the attribute doesn't exist, and trying to set it to something that isn't a string will turn it into one before assignment.\n\n<!-- annotations\nattr foo: Maps to get/setAttribute('data-foo')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr foo = 'Hello'\n\n  connectedCallback() {\n    console.assert(this.foo === 'Hello')\n    this.foo = null // TypeScript won't like this!\n    console.assert(this.foo === 'null')\n    delete this.dataset.foo // Removes the attribute\n    console.assert(this.foo === '') // If the attribute doesn't exist, its an empty string!\n  }\n}\n```\n\n#### Boolean Attributes\n\nIf an attribute is first set to a boolean, then it can only ever be a boolean during the lifetime of an element. Boolean properties check for _presence_ of an attribute, sort of like how [`required`, `disabled` & `readonly` attributes work on forms](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes#boolean_attributes) The property will return `false` if the attribute doesn't exist, and `true` if it does, regardless of the value. If the property is set to `false` then `removeAttribute` is called, whereas `setAttribute(name, '')` is called when setting to a truthy value.\n\n<!-- annotations\nattr foo: Maps to has/toggleAttribute('data-foo')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr foo = false\n\n  connectedCallback() {\n    console.assert(this.hasAttribute('data-foo') === false)\n    this.foo = true\n    console.assert(this.hasAttribute('data-foo') === true)\n    this.setAttribute('data-foo', 'this value doesnt matter!')\n    console.assert(this.foo === true)\n  }\n}\n```\n\n#### Number Attributes\n\nIf an attribute is first set to a number, then it can only ever be a number during the lifetime of an element. This is sort of like the [`maxlength` attribute on inputs](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/maxlength). The property will return `0` if the attribute doesn't exist, and will be coerced to `Number` if it does - this means it is _possible_ to get back `NaN`. Negative numbers and floats are also valid.\n\n<!-- annotations\nattr foo: Maps to get/setAttribute('data-foo')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr foo = 1\n\n  connectedCallback() {\n    console.assert(this.getAttribute('data-foo') === '1')\n    this.setAttribute('data-foo', 'not a number')\n    console.assert(Number.isNaN(this.foo))\n    this.foo = -3.14\n    console.assert(this.getAttribute('data-foo') === '-3.14')\n  }\n}\n```\n\n### Default Values\n\nWhen an element gets connected to the DOM, the attr is initialized. During this phase Catalyst will determine if the default value should be applied. The default value is defined in the class property. The basic rules are as such:\n\n - If the class property has a value, that is the _default_\n - When connected, if the element _does not_ have a matching attribute, the default _is_ applied.\n - When connected, if the element _does_ have a matching attribute, the default _is not_ applied, the property will be assigned to the value of the attribute instead.\n\n{% capture callout %}\nRemember! The values defined in the class field are the _default_. They won't be set if the element is created and its attribute set to a custom value!\n{% endcapture %}{% include callout.md %}\n\nThe following example illustrates this behavior:\n\n<!-- annotations\nattr name: Maps to get/setAttribute('data-name')\n-->\n\n```js\nimport { controller, attr } from \"@github/catalyst\"\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr name = 'World'\n  connectedCallback() {\n    this.textContent = `Hello ${this.name}`\n  }\n}\n```\n\n<!-- annotations\ndata-name \".*\": Will set the value of `name`\n-->\n\n```html\n<hello-world></hello-world>\n// This will render `Hello World`\n\n<hello-world data-name=\"Catalyst\"></hello-world>\n// This will render `Hello Catalyst`\n\n<hello-world data-name=\"\"></hello-world>\n// This will render `Hello `\n```\n\n### What about without Decorators?\n\nIf you're not using decorators, then you won't be able to use the `@attr` decorator, but there is still a way to achieve the same result. Under the hood `@attr` simply tags a field, but `initializeAttrs` and `defineObservedAttributes` do all of the logic.\n\nCalling `initializeAttrs` in your connected callback, with the list of properties you'd like to initialize, and calling `defineObservedAttributes` with the class, can achieve the same result as `@attr`. The class fields can still be defined in your class, and they'll be overridden as described above. For example:\n\n```js\nimport {initializeAttrs, defineObservedAttributes} from '@github/catalyst'\n\nclass HelloWorldElement extends HTMLElement {\n  foo = 1\n\n  connectedCallback() {\n    initializeAttrs(this, ['foo'])\n  }\n\n}\ndefineObservedAttributes(HelloWorldElement, ['foo'])\n```\n\nThis example is functionally identical to:\n\n```js\nimport {controller, attr} from '@github/catalyst'\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr foo = 1\n}\n```\n"
  },
  {
    "path": "docs/_guide/conventions-2.md",
    "content": "---\nversion: 2\nchapter: 13\ntitle: Conventions\nsubtitle: Common naming and patterns\npermalink: /guide-v2/conventions\n---\n\nCatalyst strives for convention over code. Here are a few conventions we recommend when writing Catalyst code:\n\n### Suffix your controllers consistently, for symmetry\n\nCatalyst components can be suffixed with `Element`, `Component` or `Controller`. We think elements should behave as closely to the built-ins as possible, so we like to use `Element` (existing elements do this, for example `HTMLDivElement`, `SVGElement`). If you're using a server side comoponent framework such as [ViewComponent](https://viewcomponent.org/), it's probably better to suffix `Component` for symmetry with that framework.\n\n```typescript\n@controller\nclass UserListElement extends HTMLElement {} // `<user-list />`\n```\n\n```typescript\n@controller\nclass UserListComponent extends HTMLElement {} // `<user-list />`\n```\n\n### The best class-names are two word descriptions\n\nCustom elements are required to have a `-` inside the tag name. Catalyst's `@controller` will derive the tag name from the class name - and so as such the class name needs to have at least two capital letters, or to put it another way, it needs to consist of at least two CamelCased words. The element name should describe what it does succinctly in two words. Some examples:\n\n - `theme-picker` (`class ThemePickerElement`)\n - `markdown-toolbar` (`class MarkdownToolbarElement`)\n - `user-list` (`class UserListElement`)\n - `content-pager` (`class ContentPagerElement`)\n - `image-gallery` (`class ImageGalleryElement`)\n\nIf you're struggling to come up with two words, think about one word being the \"what\" (what does it do?) and another being the \"how\" (how does it do it?).\n\n### Keep class-names short (but not too short)\n\nBrevity is good, element names are likely to be typed out a lot, especially throughout HTML in as tag names, and `data-target`, `data-action` attributes. A good rule of thumb is to try to keep element names down to less than 15 characters (excluding the `Element` suffix), and ideally less than 10. Also, longer words are generally harder to spell, which means mistakes might creep into your code.\n\nBe careful not to go too short! We'd recommend avoiding contracting words such as using `Img` to mean `Image`. It can create confusion, especially if there are inconsistencies across your code!\n\n### Method names should describe what they do\n\nA good method name, much like a good class name, describes what it does, not how it was invoked. While methods can be given most names, you should avoid names that conflict with existing methods on the `HTMLElement` prototype (more on that in [anti-patterns]({{ site.baseurl }}/guide/anti-patterns#avoid-shadowing-method-names)). Names like `onClick` are best avoided, overly generic names like `toggle` should also be avoided. Just like class names it is a good idea to ask \"how\" and \"what\", so for example `showAdmins`, `filterUsers`, `updateURL`.\n\n### `@target` should use singular naming, while `@targets` should use plural\n\nTo help differentiate the two `@target`/`@targets` decorators, the properties should be named with respective to their cardinality. That is to say, if you're using an `@target` decorator, then the name should be singular (e.g. `user`, `field`) while the `@targets` decorator should be coupled with plural property names (e.g. `users`, `fields`).\n\n"
  },
  {
    "path": "docs/_guide/conventions.md",
    "content": "---\nversion: 1\nchapter: 9\ntitle: Conventions\nsubtitle: Common naming and patterns\n---\n\nCatalyst strives for convention over code. Here are a few conventions we recommend when writing Catalyst code:\n\n### Use `Element` to suffix your controller class\n\nBuilt in HTML elements all extend from the `HTMLElement` constructor, and are all suffixed with `Element` (for example `HTMLElement`, `SVGElement`, `HTMLInputElement` and so on). Catalyst components should be no different, they should behave as closely to the built-ins as possible.\n\n```typescript\n@controller\nclass UserListElement extends HTMLElement {}\n```\n\n### The best class-names are two word descriptions\n\nCustom elements are required to have a `-` inside the tag name. Catalyst's `@controller` will derive the tag name from the class name - and so as such the class name needs to have at least two capital letters, or to put it another way, it needs to consist of at least two CamelCased words. The element name should describe what it does succinctly in two words. Some examples:\n\n - `theme-picker` (`class ThemePickerElement`)\n - `markdown-toolbar` (`class MarkdownToolbarElement`)\n - `user-list` (`class UserListElement`)\n - `content-pager` (`class ContentPagerElement`)\n - `image-gallery` (`class ImageGalleryElement`)\n\nIf you're struggling to come up with two words, think about one word being the \"what\" (what does it do?) and another being the \"how\" (how does it do it?).\n\n### Keep class-names short (but not too short)\n\nBrevity is good, element names are likely to be typed out a lot, especially throughout HTML in as tag names, and `data-target`, `data-action` attributes. A good rule of thumb is to try to keep element names down to less than 15 characters (excluding the `Element` suffix), and ideally less than 10. Also, longer words are generally harder to spell, which means mistakes might creep into your code.\n\nBe careful not to go too short! We'd recommend avoiding contracting words such as using `Img` to mean `Image`. It can create confusion, especially if there are inconsistencies across your code!\n\n### Method names should describe what they do\n\nA good method name, much like a good class name, describes what it does, not how it was invoked. While methods can be given most names, you should avoid names that conflict with existing methods on the `HTMLElement` prototype (more on that in [anti-patterns]({{ site.baseurl }}/guide/anti-patterns#avoid-shadowing-method-names)). Names like `onClick` are best avoided, overly generic names like `toggle` should also be avoided. Just like class names it is a good idea to ask \"how\" and \"what\", so for example `showAdmins`, `filterUsers`, `updateURL`.\n\n### `@target` should use singular naming, while `@targets` should use plural\n\nTo help differentiate the two `@target`/`@targets` decorators, the properties should be named with respective to their cardinality. That is to say, if you're using an `@target` decorator, then the name should be singular (e.g. `user`, `field`) while the `@targets` decorator should be coupled with plural property names (e.g. `users`, `fields`).\n"
  },
  {
    "path": "docs/_guide/create-ability.md",
    "content": "---\nversion: 2\nchapter: 9\ntitle: Create Ability\nsubtitle: Create your own abilities\npermalink: /guide-v2/create-ability\n---\n\nCatalyst provides the functionality to create your own abilities, with a few helper methods and a `controllable` base-level ability. These are explained in detail below, but for a quick summary they are:\n\n - `createAbility` - a helper function to make new abilities (class decorators).\n - `createMark` - a helper function to generate class field & method decorators.\n - `tag-observer` - a set of helper functions to watch for tagged children in an element's subtree.\n - `controllable` - the base ability which allows interacting with semi-private parts of an element.\n\n## createAbility\n\nThis function allows you to make your own [Ability]({{ site.baseurl }}/guide/abilities). Abilities are really Class Decorators, but there's a couple of things that `createAbility` provides to simplify the ergonomics of Class Decorators:\n\n - TypeScript can be a little tricky when working with Class Decorators. `createAbility` simplifies this a bit.\n - JavaScript does not copy over the `name` property when extending a class (e.g. via a decorator), and it can be a little cumbersome to do this, so `createAbility` does this for you.\n - Abilities are [idempotent](https://en.wikipedia.org/wiki/Idempotence). Class decorators are not idempotent by default, which means applying a decorator multiple times can cause issues. `createAbility` mitigates this by memoizing the classes it has applied to, meaning applying an ability multiple times has no effect past the first application.\n\nThe above three features of `createAbility` make it really useful when creating mixins for web components, and makes them much easier for developers as they can trust an ability to not be sensitive to these problems.\n\nTo create an ability, call the `createAbility` method and pass in a callback function which takes a `CustomElementClass` and returns a new class. You can also provide extra types if your returned class adds new methods or fields. Here's an example, using TypeScript:\n\n\n```typescript\nimport type {CustomElementClass} from '@github/catalyst'\nimport {createAbility} from '@github/catalyst'\n\n// by convention, abilities end in \"able\"\ninterface Fooable {\n  foo(): void // This interface has additional methods on top of `CustomElementClass`!\n}\n\n// Fooable: automatically calls `foo()` on `connectedCallback`\nexport const fooable = createAbility(\n  //                                          ↓ Notice the `& { new (): Fooable }`\n  <T extends CustomElementClass>(Class: T): T & { new (): Fooable } =>\n    class extends Class {\n      connectedCallback() {\n        this.foo()\n      }\n\n      foo() {\n        console.log('Foo was called!')\n      }\n    }\n)\n```\n\nInside the `class extends Class` block, you can author custom element logic that you might want to make reusable across a multitude of elements. You can also adjust the input type to subclass `CustomElementClass`, which can be useful for setting up a contract between your Ability and the classes that rely on it:\n\n```typescript\nimport type {CustomElementClass} from '@github/catalyst'\nimport {createAbility} from '@github/catalyst'\n\n// by convention, abilities end in \"able\"\ninterface Fooable {\n  foo(): void // This interface has additional methods on top of `CustomElementClass`!\n}\n\ninterface FooableClass {\n  new(...args: any[]): Fooable\n}\n\n// Fooable: automatically calls `foo()` on `connectedCallback`\nexport const fooable = createAbility(\n  //                            ↓ Notice the `& FooableClass`\n  <T extends CustomElementClass & FooableClass>(Class: T): T =>\n    class extends Class {\n      // TypeScript will expect the constructor to be defined for a mixin\n      constructor(...args: any[]) {\n        super(...args)\n      }\n\n      connectedCallback() {\n        // Classes that apply this ability _must_ implement `foo()`.\n        super.foo()\n      }\n    }\n```\n\nIf you're interested in some advanced examples, you can take a look at the Catalyst source code - every feature of Catalyst is an Ability!\n\n## createMark\n\nThis function allows you to make annotations for fields (like `@attr` and `@target`). Marks are really Field/Method Decorators, but with simpler ergonomics:\n\n - Marks are only initialized on instances, which makes them easier to reason about.\n - Marks are not configurable, which keeps them simple.\n - They are built to ease a transition between TypeScript decorators and ECMAScript decorators, which will help as decorators become standardised.\n\n`createMark` can be called with a `validate` and an `init` function, and gives back a tuple of 3 functions: the decorator itself, a function to get a list of marks that an instance has, and a function that will initialise the marks on an instance. It can be used like so:\n\n```typescript\n\n// Makes the @prop decorator\nconst [prop, getProps, initProps] = createMark(\n  ({name, kind}) => {\n    // Validate the name and kind that a mark can have.\n    // Name will be the PropertyKey that was decorated, and `kind` will be one of:\n    // \"method\", \"field\", \"getter\", \"setter\".\n    if (kind === \"method\") {\n      throw new Error(`@prop cannot be used to mark a method`)\n    }\n  },\n  (instance: CustomElement, {name, kind, access}) => {\n    // Put field initialization logic here.\n    // Return a property descriptor to define a field's functionality:\n    let value = kind === 'field' ? access.value : access.get?.call(instance)\n    return {\n      get() { return value }\n      set(newValue) {\n        value = newValue\n        instance.propChanged(name, newValue)\n      }\n    }\n  }\n)\n```\n\nIf you want to find some examples of how marks work, take a look at the Catalyst source code! All field decorators (`@attr`, `@target`, `@provide`, `@consume` and so on) use `createMark`.\n\n## tag-observer\n\nTag Observer provides a set of functions to observe elements marked with well-known attributes across the DOM, allowing classes to be reactive to DOM mutations. These functions operate over a `MutationObserver` set up to detect new elements coming into the page that have a registered attribute. To call register a new tag you can use the `registerTag` function which takes an attribute name to observe, a parse function (that parses the attribute value), and a found function (which is called for each element that has the attribute):\n\n```typescript\nregisterTag(\n  `data-foo`,\n  (value: string) => value.split('.'),\n  (el: Element, controller: Element | ShadowRoot, ...meta: string[]) => {\n    // ...\n  }\n)\n```\n\nTag Observer also provides a `observeElementForTags` function, which can be called on an element to adopt it into observation. A good place to use this is in your Abilities `connectedCallback`. This function can also take a `shadowRoot` if you're interested in observing tags within the shadow DOM (recommended). This function will find the root element (`ownerDocument`) and begin observing it.\n\n```typescript\nexport const fooable = createAbility(\n  <T extends CustomElementClass>(Class: T): T =>\n    class extends Class {\n      connectedCallback() {\n        observeElementForTags(this) // This elements ownerDocument will now look out for new tags\n      }\n    }\n```\n\nWhenever an element appears on the page with the matching attribute (e.g. `data-foo`), the value is extracted, split by whitespace, and each substring is then given to `parse` to turn into an array of strings. The first value in the array that the parse function returns must be a parent selector, which is then used to find the controller this attribute could pertain to. If the element is a child of the given controller selector, then the found function is called with the element, the controller, and any additional metadata that the parse function extracted. Let's see an example for how this might work, given the above registered tag:\n\n```html\n<my-element>\n  <div data-foo=\"my-element.foo.bar other-element.baz.bing\"></div>\n</my-element>\n```\n\n- Our `data-foo` attribute is found in the DOM, belonging to the `div` element.\n- The value is extracted and split by whitespace.\n- Our parse function gets called twice, firstly with `my-element.foo.bar`\n  - The parse function splits this by `.` which gets us `['my-element', 'foo', 'bar']`.\n  - Tag observer uses `my-element` as the parent selector and calls `div.closest('my-element')`,\n  - The `<my-element>` controller is found.\n  - Our found function is called with `(<div data-foo=\"...\"/>, <my-element/>, ['foo', 'bar'])`\n- The parse function is also called with `other-element.baz.bing`.\n  - The parse function splits this by `.` which gets us `['other-element', 'baz', 'bing']`.\n  - Tag observer uses `other-element` as the parent selector and calls `div.closest('other-element')`,\n  - No parent element is found, so the found function is not called.\n\nTo take a look at how Tag Observer is used in Catalyst, you can look at [`data-action` (the Actionable ability)]({{ site.baseurl }}/guide/actions) or [`data-target` & `data-targets` (the Targetable ability)]({{ site.baseurl }}/guide/targets).\n\n## controllable\n\n`controllable` is a basic ability which other abilities can use to simplify connecting to a custom elements private state. This ability isn't _required_ to be used when creating your own abilities, but it's very useful for abilities which expect to use either the [ShadowDOM](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot) or [ElementInternals](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals).\n\nYou can create an ability that itself uses the `controllable` ability like so:\n\n```typescript\nimport type {CustomElementClass} from '@github/catalyst'\nimport {createAbility, controllable} from '@github/catalyst'\n\ncreateAbility((Class: CustomElementClass) => class extends controllable(Class) {\n  // Your behaviour goes here!\n}\n```\n\nThe `controllable` ability provides 2 _custom_ callbacks which allow you to safely & robustly intercept the attachment of a ShadowRoot, and the attachment of ElementInternals. Let's look at each:\n\n### `[attachShadowCallback](shadowRoot: ShadowRoot)`\n\n```typescript\nimport type {CustomElementClass} from '@github/catalyst'\nimport {createAbility, attachShadowCallback, controllable} from '@github/catalyst'\n\ncreateAbility((Class: CustomElementClass) => class extends controllable(Class) {\n  [attachShadowCallback](shadowRoot: ShadowRoot) {\n    super[attachShadowCallback](shadowRoot)\n    // Do stuff with the `shadowRoot`.\n  }\n}\n```\n\n`attachShadowCallback` is a special `Symbol()` which allows you to make a method mostly hidden from other classes. `controllable` will call this symbol method whenever a ShadowRoot is attached to the element, which can be attached in 2 different ways:\n\n - During the constructor, where the element might recieve a declarative ShadowDOM root (closed or open).\n - Any time the `attachShadow()` function is called.\n\nThis method is _usually_ called zero or once, but may be called twice if the element recieves a Declarative ShadowDOM root, and overrides this with another call to `attachShadow()`.\n\nSimply overriding `this.attachShadow` or trying to access `this.shadowRoot` can be a little tricky (if an element has a closed declarative shadow root this can be especially difficult to access within mixins), so this callback can be especially useful for working around the various ways a shadowRoot can be created.\n\n### `[attachInternalsCallback](internals: ElementInternals)`\n\n```typescript\nimport type {CustomElementClass} from '@github/catalyst'\nimport {createAbility, attachInternalsCallback, controllable} from '@github/catalyst'\n\ncreateAbility((Class: CustomElementClass) => class extends controllable(Class) {\n  [attachInternalsCallback](internals: ElementInternals) {\n    super[attachInternalsCallback](internals)\n    // Do stuff with the `internals`.\n  }\n}\n```\n\n`attachInternalsCallback` is a special `Symbol()` which allows you to make a method mostly hidden from other classes. `controllable` will call this symbol method whenever an element is constructed, giving it the element's `ElementInternals`. This enables custom enablies [Abilities]({{ site.baseurl }}/guide/abilities) to also have access to `ElementInternals`. It does so while also preserving the ability for `attachInternals()` to be called again (usually `attachInternals()` will error if called twice).\n\nIf you need access to the internals, then the `attachInternalsCallback` can be very useful as it protects you from calling `attachInternals` in a way which the concrete classes will then fail.\n"
  },
  {
    "path": "docs/_guide/decorators-2.md",
    "content": "---\nversion: 2\nchapter: 3\ntitle: Decorators\nsubtitle: Using TypeScript for ergonomics\npermalink: /guide-v2/decorators\n---\n\nDecorators are used heavily in Catalyst, because they provide really clean ergonomics and makes using the library a lot easier. Decorators are a special, (currently) non standard, feature of TypeScript. You'll need to turn the `experimentalDecorators` option on inside of your TypeScript project to use them (if you're using `@babel/plugin-proposal-decorators` plugin, you need to use [`legacy` option](https://babeljs.io/docs/en/babel-plugin-proposal-decorators#legacy)).\n\nYou can read more about [decorators in the TypeScript handbook](https://www.typescriptlang.org/docs/handbook/decorators.html), but here's quick guide:\n\nDecorators can be used three ways:\n\n### Class Decorators\n\nCatalyst comes with the `@controller` decorator. This gets put on top of the class, like so:\n\n```js\n@controller\nclass HelloWorldElement extends HTMLElement {}\n```\n\n### Class Field Decorators\n\nCatalyst comes with the `@target` and `@targets` decorators (for more on these [read the Targets guide section]({{ site.baseurl }}/guide/targets)). These get added on top or to the left of the field name, like so:\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @target something\n  \n  // Alternative style\n  @targets\n  others\n\n}\n```\n<br>\n\nClass Field decorators get given the class and the field name so they can add custom functionality to the field. Because they operate on the fields, they must be put on top of or to the left of the field.\n\n### Method Decorators\n\nMethod decorators work just like Field Decorators. Put them on top or on the left of the method, like so:\n\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @log\n  submit() {\n    // ...\n  }\n\n  // Alternative style\n\n  @log load() {\n    // ...\n  }\n\n}\n```\n\n### Getter/Setter \n\nDecorators can also be used over a `get` or `set` field. These work just like Field Decorators, but you can put them over one or both the `get` or `set` field. Some decorators might throw an error if you put them over a `get` field, when they expect to be put over a `set` field:\n\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @target set something() {\n    // ...\n  }\n\n  // Can be used over just one field\n  @attr get data() {\n    return {}\n  }\n  set data() {\n\n  }\n}\n```\n\n### Supporting `strictPropertyInitialization`\n\nTypeScript comes with various \"strict\" mode settings, one of which is `strictPropertyInitialization` which lets TypeScript catch potential class properties which might not be assigned during construction of a class. This option conflicts with Catalyst's `@target`/`@targets` decorators, which safely do the assignment but TypeScript's simple heuristics cannot detect this. There are two ways to work around this:\n\n1. Use TypeScript's [`declare` modifier](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier) to tell TypeScript that the decorated field will still be set up correctly:\n\n    ```typescript\n    class HelloWorldElement extends HTMLElement {\n      @target declare something: HTMLElement\n      @targets declare items: HTMLElement[]\n    }\n    ```\n    \n    Note that this only works on TypeScript 3.7+, so if you're on an older version, you can also use the [definite initialization operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions) to do the same thing.\n\n2. You can also disable the compiler option (other strict mode rules can still apply) in your `tsconfig.json` like so:\n\n    ```json\n    {\n      \"compilerOptions\": {\n        \"strict\": true,\n        \"strictPropertyInitialization\": false\n      }\n    }\n    ```\n\n### Function Calling Decorators\n\nYou might see some decorators that look like function calls, and that's because they are! Some decorators allow for customisation; calling with additional arguments. Decorators that expect to be called are generally not interchangeable with the non-call variant, a decorators documentation should tell you how to use it.\n\nCatalyst doesn't ship with any decorators that can be called like a function; but an example of one can be found in the `@debounce` decorator in the [`@github/mini-throttle`](https://github.com/github/mini-throttle) package:\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @debounce(100)\n  handleInput() {\n    // ...\n  }\n\n}\n```\n<br>\n"
  },
  {
    "path": "docs/_guide/decorators.md",
    "content": "---\nversion: 1\nchapter: 3\ntitle: Decorators\nsubtitle: Using TypeScript for ergonomics\n---\n\nDecorators are used heavily in Catalyst, because they provide really clean ergonomics and makes using the library a lot easier. Decorators are a special, (currently) non standard, feature of TypeScript. You'll need to turn the `experimentalDecorators` option on inside of your TypeScript project to use them (if you're using `@babel/plugin-proposal-decorators` plugin, you need to use [`legacy` option](https://babeljs.io/docs/en/babel-plugin-proposal-decorators#legacy)).\n\nYou can read more about [decorators in the TypeScript handbook](https://www.typescriptlang.org/docs/handbook/decorators.html), but here's quick guide:\n\nDecorators can be used three ways:\n\n### Class Decorators\n\nCatalyst comes with the `@controller` decorator. This gets put on top of the class, like so:\n\n```js\n@controller\nclass HelloWorldElement extends HTMLElement {}\n```\n\n### Class Field Decorators\n\nCatalyst comes with the `@target` and `@targets` decorators (for more on these [read the Targets guide section]({{ site.baseurl }}/guide/targets)). These get added on top or to the left of the field name, like so:\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @target something\n  \n  // Alternative style\n  @targets\n  others\n\n}\n```\n<br>\n\nClass Field decorators get given the class and the field name so they can add custom functionality to the field. Because they operate on the fields, they must be put on top of or to the left of the field.\n\n### Method Decorators\n\nMethod decorators work just like Field Decorators. Put them on top or on the left of the method, like so:\n\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @log\n  submit() {\n    // ...\n  }\n\n  // Alternative style\n\n  @log load() {\n    // ...\n  }\n\n}\n```\n\n### Getter/Setter \n\nDecorators can also be used over a `get` or `set` field. These work just like Field Decorators, but you can put them over one or both the `get` or `set` field. Some decorators might throw an error if you put them over a `get` field, when they expect to be put over a `set` field:\n\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @target set something() {\n    // ...\n  }\n\n  // Can be used over just one field\n  @attr get data() {\n    return {}\n  }\n  set data() {\n\n  }\n}\n```\n\n### Supporting `strictPropertyInitialization`\n\nTypeScript comes with various \"strict\" mode settings, one of which is `strictPropertyInitialization` which lets TypeScript catch potential class properties which might not be assigned during construction of a class. This option conflicts with Catalyst's `@target`/`@targets` decorators, which safely do the assignment but TypeScript's simple heuristics cannot detect this. There are two ways to work around this:\n\n1. Use TypeScript's [`declare` modifier](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare-property-modifier) to tell TypeScript that the decorated field will still be set up correctly:\n\n    ```typescript\n    class HelloWorldElement extends HTMLElement {\n      @target declare something: HTMLElement\n      @targets declare items: HTMLElement[]\n    }\n    ```\n    \n    Note that this only works on TypeScript 3.7+, so if you're on an older version, you can also use the [definite initialization operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions) to do the same thing.\n\n2. You can also disable the compiler option (other strict mode rules can still apply) in your `tsconfig.json` like so:\n\n    ```json\n    {\n      \"compilerOptions\": {\n        \"strict\": true,\n        \"strictPropertyInitialization\": false\n      }\n    }\n    ```\n\n### Function Calling Decorators\n\nYou might see some decorators that look like function calls, and that's because they are! Some decorators allow for customisation; calling with additional arguments. Decorators that expect to be called are generally not interchangeable with the non-call variant, a decorators documentation should tell you how to use it.\n\nCatalyst doesn't ship with any decorators that can be called like a function; but an example of one can be found in the `@debounce` decorator in the [`@github/mini-throttle`](https://github.com/github/mini-throttle) package:\n\n```js\nclass HelloWorldElement extends HTMLElement {\n\n  @debounce(100)\n  handleInput() {\n    // ...\n  }\n\n}\n```\n<br>\n"
  },
  {
    "path": "docs/_guide/introduction-2.md",
    "content": "---\nversion: 2\nchapter: 1\ntitle: Introduction\nsubtitle: Origins & Concepts\npermalink: /guide-v2/introduction\n---\n\nCatalyst is a set of patterns and techniques for developing _components_ within a complex application. At its core, Catalyst simply provides a small library of functions to make developing [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) easier. The library is an implementation detail, though. The concepts are what we're most interested in.\n\n## How did we get here?\n\nGitHub's first page interactions were written using jQuery, which was widely used at the time. Eventually, as browser compatibility increased and jQuery patterns such as the Selector Pattern & easy class manipulation became standard, [GitHub moved away from jQuery](https://github.blog/2018-09-06-removing-jquery-from-github-frontend/).\n\nRather than moving to entirely new paradigms, GitHub continued to use the same concepts within jQuery. Event Delegation was still heavily used, as well as querySelector. The event delegation concept was also extended to \"element delegation\" - discovering when Elements were added to the DOM, using the [Selector Observer](https://github.com/josh/selector-observer) library.\n\nThese patterns were reduced to first principles: _Observing_ elements on the page, _listening_ to the events these elements or their children emit, and _querying_ the children of an element to mutate or extend them.\n\nThe Web Systems team at GitHub explored other tools that adopt these set of patterns and principles. The closest match to those goals was [Stimulus](https://stimulusjs.org/) (from which Catalyst is heavily inspired), but ultimately the desire to leverage technology that engineers at GitHub were already familiar with was the motivation to create Catalyst.\n\n## Three core concepts: Observe, Listen, Query\n\nCatalyst takes these three core concepts and delivers them in the lightest possible way they can be delivered.\n\n - **Observability** Catalyst solves observability by leveraging [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). Custom Elements are given unique names within a system, and the browser will automatically use the Custom Element registry to observe these Elements entering and leaving the DOM. Read more about this in the Guide Section entitled [Your First Component]({{ site.baseurl }}/guide/your-first-component).\n\n - **Listening** Event Delegation makes a great deal of sense when observing events \"high up the tree\" - registering global event listeners on the Window element - but Custom Elements sit much closer to their children within the tree, and so Direct Event binding is preferred. Catalyst solves this by binding event listeners to any descendants with `data-action` attributes. Read more about this in the Guide Section entitled [Actions]({{ site.baseurl }}/guide/actions).\n\n - **Querying** Custom Elements largely solve querying, by simply calling `querySelector` - however CSS selectors are loosely disciplined and can create unnecessary coupling to the DOM structure (e.g. by querying tag names). Catalyst extends the `data-action` concept by also using `data-target` to declare descendants that the Custom Element is interested in querying. Read more about this in the Guide Section entitled [Targets]({{ site.baseurl }}/guide/targets).\n"
  },
  {
    "path": "docs/_guide/introduction.md",
    "content": "---\nversion: 1\nchapter: 1\ntitle: Introduction\nsubtitle: Origins & Concepts\n---\n\nCatalyst is a set of patterns and techniques for developing _components_ within a complex application. At its core, Catalyst simply provides a small library of functions to make developing [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) easier. The library is an implementation detail, though. The concepts are what we're most interested in.\n\n## How did we get here?\n\nGitHub's first page interactions were written using jQuery, which was widely used at the time. Eventually, as browser compatibility increased and jQuery patterns such as the Selector Pattern & easy class manipulation became standard, [GitHub moved away from jQuery](https://github.blog/2018-09-06-removing-jquery-from-github-frontend/).\n\nRather than moving to entirely new paradigms, GitHub continued to use the same concepts within jQuery. Event Delegation was still heavily used, as well as querySelector. The event delegation concept was also extended to \"element delegation\" - discovering when Elements were added to the DOM, using the [Selector Observer](https://github.com/josh/selector-observer) library.\n\nThese patterns were reduced to first principles: _Observing_ elements on the page, _listening_ to the events these elements or their children emit, and _querying_ the children of an element to mutate or extend them.\n\nThe Web Systems team at GitHub explored other tools that adopt these set of patterns and principles. The closest match to those goals was [Stimulus](https://stimulusjs.org/) (from which Catalyst is heavily inspired), but ultimately the desire to leverage technology that engineers at GitHub were already familiar with was the motivation to create Catalyst.\n\n## Three core concepts: Observe, Listen, Query\n\nCatalyst takes these three core concepts and delivers them in the lightest possible way they can be delivered.\n\n - **Observability** Catalyst solves observability by leveraging [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). Custom Elements are given unique names within a system, and the browser will automatically use the Custom Element registry to observe these Elements entering and leaving the DOM. Read more about this in the Guide Section entitled [Your First Component]({{ site.baseurl }}/guide/your-first-component).\n\n - **Listening** Event Delegation makes a great deal of sense when observing events \"high up the tree\" - registering global event listeners on the Window element - but Custom Elements sit much closer to their children within the tree, and so Direct Event binding is preferred. Catalyst solves this by binding event listeners to any descendants with `data-action` attributes. Read more about this in the Guide Section entitled [Actions]({{ site.baseurl }}/guide/actions).\n\n - **Querying** Custom Elements largely solve querying, by simply calling `querySelector` - however CSS selectors are loosely disciplined and can create unnecessary coupling to the DOM structure (e.g. by querying tag names). Catalyst extends the `data-action` concept by also using `data-target` to declare descendants that the Custom Element is interested in querying. Read more about this in the Guide Section entitled [Targets]({{ site.baseurl }}/guide/targets).\n"
  },
  {
    "path": "docs/_guide/lazy-elements-2.md",
    "content": "---\nversion: 2\nchapter: 16\ntitle: Lazy Elements\nsubtitle: Dynamically load elements just in time\npermalink: /guide-v2/lazy-elements\n---\n\nA common practice in modern web development is to combine all JavaScript code into JS \"bundles\". By bundling the code together we avoid the network overhead of fetching each file. However the trade-off of bundling is that we might deliver JS code that will never run in the browser.\n\n![A screenshot from Chrome Devtools showing the Coverage panel. The panel has multiple request to JS assets and it shows that most of them have large chunks that are unused.](/catalyst/guide/devtools-coverage.png)\n\nAn alternative solution to bundling is to load JavaScript just in time. Downloding the JavaScript for Catalyst controllers when the browser first encounters them can be done with the `lazyDefine` function.\n\n```typescript\nimport {lazyDefine} from '@github/catalyst'\n\n// Dynamically import the Catalyst controller when the `<user-avatar>` tag is seen.\nlazyDefine('user-avatar', () => import('./components/user-avatar'))\n```\n\nServing this file allows us to defer loading of the component code until it's actually needed by the web page. The tradeoff of deferring loading is that the elements will be inert until the dynamic import of the component code resolves. Consider what your UI might look like while these components are resolving. Consider providing a loading indicator and disabling controls as the default state. The smaller the component, the faster it will resolve which means that your users might not notice a inert state. A good rule of thumb is that a component should load within 100ms on a \"Fast 3G\" connection.\n\nGenerally we think it's a good idea to `lazyDefine` all elements and then prioritize eager loading of ciritical elements as needed. You might consider using code-generation to generate a file lazy defining all your components.\n\nBy default the component will be loaded when the element is present in the document and the document has finished loading. This can happen before sub-resources such as scripts, images, stylesheets and frames have finished loading. It is possible to defer loading even later by adding a `data-load-on` attribute on your element. The value of which must be one of the following prefefined values:\n\n- `<user-avatar data-load-on=\"ready\"></user-avatar>` (default)\n\t- The element is loaded when the document has finished loading. This listens for changes to `document.readyState` and triggers when it's no longer loading.\n- `<user-avatar data-load-on=\"firstInteraction\"></user-avatar>` \n\t- This element is loaded on the first user interaction with the page. This listens for `mousedown`, `touchstart`, `pointerdown` and `keydown` events on `document`.\n- `<user-avatar data-load-on=\"visible\"></user-avatar>`\n\t- This element is loaded when it's close to being visible. Similar to `<img loading=\"lazy\" [..] />` . The functionality is driven by an `IntersectionObserver`.\n\nThis functionality is similar to the [\"Lazy Custom Element Definitions\" spec proposal](https://github.com/WICG/webcomponents/issues/782) and as this proposal matures we see Catalyst conforming to the spec and leveraging this new API to lazy load elements.\n"
  },
  {
    "path": "docs/_guide/lazy-elements.md",
    "content": "---\nversion: 1\nchapter: 13\ntitle: Lazy Elements\nsubtitle: Dynamically load elements just in time\n---\n\nA common practice in modern web development is to combine all JavaScript code into JS \"bundles\". By bundling the code together we avoid the network overhead of fetching each file. However the trade-off of bundling is that we might deliver JS code that will never run in the browser.\n\n![A screenshot from Chrome Devtools showing the Coverage panel. The panel has multiple request to JS assets and it shows that most of them have large chunks that are unused.](/catalyst/guide/devtools-coverage.png)\n\nAn alternative solution to bundling is to load JavaScript just in time. Downloding the JavaScript for Catalyst controllers when the browser first encounters them can be done with the `lazyDefine` function.\n\n```typescript\nimport {lazyDefine} from '@github/catalyst'\n\n// Dynamically import the Catalyst controller when the `<user-avatar>` tag is seen.\nlazyDefine('user-avatar', () => import('./components/user-avatar'))\n```\n\nServing this file allows us to defer loading of the component code until it's actually needed by the web page. The tradeoff of deferring loading is that the elements will be inert until the dynamic import of the component code resolves. Consider what your UI might look like while these components are resolving. Consider providing a loading indicator and disabling controls as the default state. The smaller the component, the faster it will resolve which means that your users might not notice a inert state. A good rule of thumb is that a component should load within 100ms on a \"Fast 3G\" connection.\n\nGenerally we think it's a good idea to `lazyDefine` all elements and then prioritize eager loading of ciritical elements as needed. You might consider using code-generation to generate a file lazy defining all your components.\n\nBy default the component will be loaded when the element is present in the document and the document has finished loading. This can happen before sub-resources such as scripts, images, stylesheets and frames have finished loading. It is possible to defer loading even later by adding a `data-load-on` attribute on your element. The value of which must be one of the following prefefined values:\n\n- `<user-avatar data-load-on=\"ready\"></user-avatar>` (default)\n\t- The element is loaded when the document has finished loading. This listens for changes to `document.readyState` and triggers when it's no longer loading.\n- `<user-avatar data-load-on=\"firstInteraction\"></user-avatar>` \n\t- This element is loaded on the first user interaction with the page. This listens for `mousedown`, `touchstart`, `pointerdown` and `keydown` events on `document`.\n- `<user-avatar data-load-on=\"visible\"></user-avatar>`\n\t- This element is loaded when it's close to being visible. Similar to `<img loading=\"lazy\" [..] />` . The functionality is driven by an `IntersectionObserver`.\n\nThis functionality is similar to the [\"Lazy Custom Element Definitions\" spec proposal](https://github.com/WICG/webcomponents/issues/782) and as this proposal matures we see Catalyst conforming to the spec and leveraging this new API to lazy load elements.\n"
  },
  {
    "path": "docs/_guide/lifecycle-hooks-2.md",
    "content": "---\nversion: 2\nchapter: 10\ntitle: Lifecycle Hooks\nsubtitle: Observing the life cycle of an element\npermalink: /guide-v2/lifecycle-hooks\n---\n\nCatalyst Controllers - like many other frameworks - have several \"well known\" method names which are called periodically through the life cycle of the element, and let you observe when an element changes in various ways. Here is a comprehensive list of all life-cycle callbacks. Each one is suffixed `Callback`, to denote that it will be called by the framework.\n\n### `connectedCallback()`\n\nThe [`connectedCallback()` is part of Custom Elements][ce-callbacks], and gets fired as soon as your element is _appended_ to the DOM. This callback is a good time to initialize any variables, perhaps add some global event listeners, or start making any early network requests.\n\nJavaScript traditionally uses the `constructor()` callback to listen for class creation. While this still works for Custom Elements, it is best avoided as the element won't be in the DOM when `constructor()` is fired, limiting its utility.\n\n#### Things to remember\n\nThe `connectedCallback` is called _as soon as_ the element is attached to a `document`. This _may_ occur _before_ an element has any children appended to it, so you should be careful not expect an element to have children during a `connectedCallback` call. This means avoiding checking any `target`s or using other methods like `querySelector`. Instead use this function to initialize itself and avoid doing initialization work which depend on children existing.\n\nIf your element depends heavily on its children existing, consider adding a [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) in the `connectedCallback` to track when your elements children change.\n\n### `attributeChangedCallback()`\n\nThe [`attributeChangedCallback()` is part of Custom Elements][ce-callbacks], and gets fired when _observed attributes_ are added, changed, or removed from your element. It required you set a `static observedAttributes` array on your class, the values of which will be any attributes that will be observed for mutations. This is given a set of arguments, the signature of your function should be:\n\n```typescript\nattributeChangedCallback(name: string, oldValue: string|null, newValue: string|null): void {}\n```\n\n#### Things to remember\n\nThe `attributeChangedCallback` will fire whenever `setAttribute` is called with an observed attribute, even if the _new_ value is the same as the _old_ value. In other words, it is possible for `attributeChangedCallback` to be called when `oldValue === newValue`. In most cases this really won't matter much, and in some cases this is very helpful; but sometimes this can bite, especially if you have [non-idempotent](https://en.wikipedia.org/wiki/Idempotence#Computer_science_examples) code inside your `attributeChangedCallback`. Try to make sure operations inside `attributeChangedCallback` are idempotent, or perhaps consider adding a check to ensure `oldValue !== newValue` before performing operations which may be sensitive to this.\n\n### `disconnectedCallback()`\n\nThe [`disconnectedCallback()` is part of Custom Elements][ce-callbacks], and gets fired as soon as your element is _removed_ from the DOM. Event listeners will automatically be cleaned up, and memory will be freed automatically from JavaScript, so you're unlikely to need this callback for much.\n\n### `adoptedCallback()`\n\nThe [`adoptedCallback()` is part of Custom Elements][ce-callbacks], and gets called when your element moves from one `document` to another (such as an iframe). It's very unlikely to occur, you'll almost never need this.\n\n[ce-callbacks]: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#Using_the_lifecycle_callbacks\n"
  },
  {
    "path": "docs/_guide/lifecycle-hooks.md",
    "content": "---\nversion: 1\nchapter: 7\ntitle: Lifecycle Hooks\nsubtitle: Observing the life cycle of an element\n---\n\nCatalyst Controllers - like many other frameworks - have several \"well known\" method names which are called periodically through the life cycle of the element, and let you observe when an element changes in various ways. Here is a comprehensive list of all life-cycle callbacks. Each one is suffixed `Callback`, to denote that it will be called by the framework.\n\n### `connectedCallback()`\n\nThe [`connectedCallback()` is part of Custom Elements][ce-callbacks], and gets fired as soon as your element is _appended_ to the DOM. This callback is a good time to initialize any variables, perhaps add some global event listeners, or start making any early network requests.\n\nJavaScript traditionally uses the `constructor()` callback to listen for class creation. While this still works for Custom Elements, it is best avoided as the element won't be in the DOM when `constructor()` is fired, limiting its utility.\n\n#### Things to remember\n\nThe `connectedCallback` is called _as soon as_ the element is attached to a `document`. This _may_ occur _before_ an element has any children appended to it, so you should be careful not expect an element to have children during a `connectedCallback` call. This means avoiding checking any `target`s or using other methods like `querySelector`. Instead use this function to initialize itself and avoid doing initialization work which depend on children existing.\n\nIf your element depends heavily on its children existing, consider adding a [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) in the `connectedCallback` to track when your elements children change.\n\n### `attributeChangedCallback()`\n\nThe [`attributeChangedCallback()` is part of Custom Elements][ce-callbacks], and gets fired when _observed attributes_ are added, changed, or removed from your element. It required you set a `static observedAttributes` array on your class, the values of which will be any attributes that will be observed for mutations. This is given a set of arguments, the signature of your function should be:\n\n```typescript\nattributeChangedCallback(name: string, oldValue: string|null, newValue: string|null): void {}\n```\n\n#### Things to remember\n\nThe `attributeChangedCallback` will fire whenever `setAttribute` is called with an observed attribute, even if the _new_ value is the same as the _old_ value. In other words, it is possible for `attributeChangedCallback` to be called when `oldValue === newValue`. In most cases this really won't matter much, and in some cases this is very helpful; but sometimes this can bite, especially if you have [non-idempotent](https://en.wikipedia.org/wiki/Idempotence#Computer_science_examples) code inside your `attributeChangedCallback`. Try to make sure operations inside `attributeChangedCallback` are idempotent, or perhaps consider adding a check to ensure `oldValue !== newValue` before performing operations which may be sensitive to this.\n\n### `disconnectedCallback()`\n\nThe [`disconnectedCallback()` is part of Custom Elements][ce-callbacks], and gets fired as soon as your element is _removed_ from the DOM. Event listeners will automatically be cleaned up, and memory will be freed automatically from JavaScript, so you're unlikely to need this callback for much.\n\n### `adoptedCallback()`\n\nThe [`adoptedCallback()` is part of Custom Elements][ce-callbacks], and gets called when your element moves from one `document` to another (such as an iframe). It's very unlikely to occur, you'll almost never need this.\n\n[ce-callbacks]: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#Using_the_lifecycle_callbacks\n"
  },
  {
    "path": "docs/_guide/patterns-2.md",
    "content": "---\nversion: 2\nchapter: 14\ntitle: Patterns\nsubtitle: Best Practices for behaviours\npermalink: /guide-v2/patterns\n---\n\nAn aim of Catalyst is to be as light weight as possible, and so we often avoid including helper functions for otherwise fine code. We also want to keep Catalyst focussed, and so where some helper functions might be reasonable, we recommend judicious use of other small libraries.\n\nHere are a few common patterns which we've avoided introducing into the Catalyst code base, and instead encourage you to take the example code and run with that:\n\n### Debouncing or Throttling events\n\nOften times you'll want to do something computationally intensive (or network intensive) based on a user event. It's worth throttling the amount of times a function can be called for these events, to prevent saturation of the CPU or network. For this we can use the \"debounce\" or \"throttle\" patterns. We recommend using the [`@github/mini-throttle`](https://github.com/github/mini-throttle) library for this, which provides throttling decorators for methods:\n\n```typescript\nimport {controller} from '@github/catalyst'\nimport {debounce} from '@github/mini-throttle/decorators'\n\n@controller\nclass FuzzySearchElement extends HTMLElement {\n\n  // Adding `@debounce(100)` here means this method will only be called once in a 100ms period.\n  @debounce(100)\n  search(event: Event) {\n    const value = event.currentTarget.value\n    // This function is very computationally intensive, so we should run it as little as possible\n    this.filterAllItemsWithValue(value)\n  }\n\n}\n```\n\nAlternatively, if you'd like more precise control over the exact way debouncing happens (for example you'd like to make the debounce timeout dynamic, or sometimes call _without_ debouncing), you can have two methods following the pattern of `foo`/`fooNow` or `foo`/`fooSync`, where the non-suffixed method dispatches asynchronously to the `Now`/`Sync` suffixed method, a little like this:\n\n```typescript\nimport {controller} from '@github/catalyst'\n\n@controller\nclass FuzzySearchElement extends HTMLElement {\n\n  #searchAnimationFrame = 0\n  search(event: Event) {\n    clearAnimationFrame(this.#searchAnimationFrame)\n    this.#searchAnimationFrame = requestAnimationFrame(() => this.searchNow(event: Event))\n  }\n  \n  searchNow(event: Event) {\n    const value = event.currentTarget.value\n    // This function is very computationally intensive, so we should run it as little as possible\n    this.filterAllItemsWithValue(value)\n  }\n\n}\n```\n\n### Aborting Network Requests\n\nWhen making network requests using `fetch`, based on user input, you can cancel old requests as new ones come in. This is useful for performance as well as UI responsiveness, as old requests that aren't cancelled might complete later than newer ones, and causing the UI to jump around. Aborting network requests requires you to use [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) (a web platform feature).\n\n```typescript\n@controller\nclass RemoveSearchElement extends HTMLElement {\n\n  #remoteSearchController: AbortController|null\n\n  async search(event: Event) {\n    // Abort the old Request\n    this.#remoteSearchController?.abort()\n\n    // To start making a new request, construct an AbortController\n    const {signal} = (this.#remoteSearchController = new AbortController())\n\n    try {\n      const res = await fetch(myUrl, {signal})\n\n      // ... Add logic here with the completed network response\n    } catch (e) {\n\n      // ... Add logic here if you need to report a failed network request.\n      // Do not rethrow for network errors!\n\n    }\n\n    if (signal.aborted) {\n      // Here you can add logic for if the request was cancelled, but\n      // usually what you want to do is just return early to avoid\n      // cleaning up the loading UI (bear in mind if the request is\n      // cancelled then another one will be in its place).\n      return\n    }\n\n    // ... Add cleanup logic here, such as removing `loading` classes.\n\n  }\n}\n```\n\n### Registering global or many event listeners\n\nGenerally speaking, you'll want to use [\"Actions\"]({{ site.baseurl }}/guide/actions) to register event listeners with your Controller, but Actions only work for components nested within your Controller. It may also be necessary to listen for events on the Document, Window, or across well-known adjacent elements. We can manually call `addEventListener` for these types, including during the `connectedCallback` phase. Cleanup for `addEventListener` can be a bit error prone, but [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) can be useful here to pass a signal that the element is cleaning up. AbortControllers should be created once per `connectedCallback`, as they are not re-usable, while Controllers _can_ be reused.\n\n\n```typescript\n@controller\nclass UnsavedChangesElement extends HTMLElement {\n\n  #eventAbortController: AbortController|null = null\n\n  connectedCallback(event: Event) {\n    // Create the new AbortController and get the new signal\n    const {signal} = (this.#eventAbortController = new AbortController())\n    \n    // You can `signal` as an option to any `addEventListener` call:\n    window.addEventListener('hashchange', this, { signal })\n    window.addEventListener('blur', this, { signal })\n    window.addEventListener('popstate', this, { signal })\n    window.addEventListener('pagehide', this, { signal })\n  }\n  \n  disconnectedCallback() {\n    // This will clean up any `addEventListener` calls which were given the `signal`\n    this.#eventAbortController?.abort()\n  }\n  \n  handleEvent(event) {\n    // `handleEvent` will be called when each one of the event listeners\n    // defined in `connectedCallback` is dispatched.\n  }\n}\n```\n"
  },
  {
    "path": "docs/_guide/patterns.md",
    "content": "---\nversion: 1\nchapter: 10\ntitle: Patterns\nsubtitle: Best Practices for behaviours\n---\n\nAn aim of Catalyst is to be as light weight as possible, and so we often avoid including helper functions for otherwise fine code. We also want to keep Catalyst focussed, and so where some helper functions might be reasonable, we recommend judicious use of other small libraries.\n\nHere are a few common patterns which we've avoided introducing into the Catalyst code base, and instead encourage you to take the example code and run with that:\n\n### Debouncing or Throttling events\n\nOften times you'll want to do something computationally intensive (or network intensive) based on a user event. It's worth throttling the amount of times a function can be called for these events, to prevent saturation of the CPU or network. For this we can use the \"debounce\" or \"throttle\" patterns. We recommend using the [`@github/mini-throttle`](https://github.com/github/mini-throttle) library for this, which provides throttling decorators for methods:\n\n```typescript\nimport {controller} from '@github/catalyst'\nimport {debounce} from '@github/mini-throttle/decorators'\n\n@controller\nclass FuzzySearchElement extends HTMLElement {\n\n  // Adding `@debounce(100)` here means this method will only be called once in a 100ms period.\n  @debounce(100)\n  search(event: Event) {\n    const value = event.currentTarget.value\n    // This function is very computationally intensive, so we should run it as little as possible\n    this.filterAllItemsWithValue(value)\n  }\n\n}\n```\n\nAlternatively, if you'd like more precise control over the exact way debouncing happens (for example you'd like to make the debounce timeout dynamic, or sometimes call _without_ debouncing), you can have two methods following the pattern of `foo`/`fooNow` or `foo`/`fooSync`, where the non-suffixed method dispatches asynchronously to the `Now`/`Sync` suffixed method, a little like this:\n\n```typescript\nimport {controller} from '@github/catalyst'\n\n@controller\nclass FuzzySearchElement extends HTMLElement {\n\n  #searchAnimationFrame = 0\n  search(event: Event) {\n    clearAnimationFrame(this.#searchAnimationFrame)\n    this.#searchAnimationFrame = requestAnimationFrame(() => this.searchNow(event: Event))\n  }\n  \n  searchNow(event: Event) {\n    const value = event.currentTarget.value\n    // This function is very computationally intensive, so we should run it as little as possible\n    this.filterAllItemsWithValue(value)\n  }\n\n}\n```\n\n### Aborting Network Requests\n\nWhen making network requests using `fetch`, based on user input, you can cancel old requests as new ones come in. This is useful for performance as well as UI responsiveness, as old requests that aren't cancelled might complete later than newer ones, and causing the UI to jump around. Aborting network requests requires you to use [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) (a web platform feature).\n\n```typescript\n@controller\nclass RemoveSearchElement extends HTMLElement {\n\n  #remoteSearchController: AbortController|null\n\n  async search(event: Event) {\n    // Abort the old Request\n    this.#remoteSearchController?.abort()\n\n    // To start making a new request, construct an AbortController\n    const {signal} = (this.#remoteSearchController = new AbortController())\n\n    try {\n      const res = await fetch(myUrl, {signal})\n\n      // ... Add logic here with the completed network response\n    } catch (e) {\n\n      // ... Add logic here if you need to report a failed network request.\n      // Do not rethrow for network errors!\n\n    }\n\n    if (signal.aborted) {\n      // Here you can add logic for if the request was cancelled, but\n      // usually what you want to do is just return early to avoid\n      // cleaning up the loading UI (bear in mind if the request is\n      // cancelled then another one will be in its place).\n      return\n    }\n\n    // ... Add cleanup logic here, such as removing `loading` classes.\n\n  }\n}\n```\n\n### Registering global or many event listeners\n\nGenerally speaking, you'll want to use [\"Actions\"]({{ site.baseurl }}/guide/actions) to register event listeners with your Controller, but Actions only work for components nested within your Controller. It may also be necessary to listen for events on the Document, Window, or across well-known adjacent elements. We can manually call `addEventListener` for these types, including during the `connectedCallback` phase. Cleanup for `addEventListener` can be a bit error prone, but [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) can be useful here to pass a signal that the element is cleaning up. AbortControllers should be created once per `connectedCallback`, as they are not re-usable, while Controllers _can_ be reused.\n\n\n```typescript\n@controller\nclass UnsavedChangesElement extends HTMLElement {\n\n  #eventAbortController: AbortController|null = null\n\n  connectedCallback(event: Event) {\n    // Create the new AbortController and get the new signal\n    const {signal} = (this.#eventAbortController = new AbortController())\n    \n    // You can `signal` as an option to any `addEventListener` call:\n    window.addEventListener('hashchange', this, { signal })\n    window.addEventListener('blur', this, { signal })\n    window.addEventListener('popstate', this, { signal })\n    window.addEventListener('pagehide', this, { signal })\n  }\n  \n  disconnectedCallback() {\n    // This will clean up any `addEventListener` calls which were given the `signal`\n    this.#eventAbortController?.abort()\n  }\n  \n  handleEvent(event) {\n    // `handleEvent` will be called when each one of the event listeners\n    // defined in `connectedCallback` is dispatched.\n  }\n}\n```\n"
  },
  {
    "path": "docs/_guide/providable.md",
    "content": "---\nversion: 2\nchapter: 8\ntitle: Providable\nsubtitle: The Provider pattern\npermalink: /guide-v2/providable\n---\n\nThe [Provider pattern](https://www.patterns.dev/posts/provider-pattern/) allows for deeply nested children to ask ancestors for values. This can be useful for decoupling state inside a component, centralising it higher up in the DOM heirarchy. A top level container component might store values, and many children can consume those values, without having logic duplicated across the app. It's quite an abstract pattern so is better explained with examples...\n\nSay for example a set of your components are built to perform actions on a user, but need a User ID. One way to handle this is to set the User ID as an attribute on each element, but this can lead to a lot of duplication. Instead these actions can request the ID from a parent component, which can provide the User ID without creating an explicit relationship (which can lead to brittle code).\n\nThe `@providable` ability allows a Catalyst controller to become a provider or consumer (or both) of one or many properties. To provide a property to nested controllers that ask for it, mark a property as `@provide` or `@provideAsync`. To consume a property from a parent, mark a property as `@consume`. Let's try implementing the user actions using `@providable`:\n\n```typescript\nimport {providable, consume, provide, controller} from '@github/catalyst'\n\n@controller\n@providable\nclass BlockUser extends HTMLElement {\n  // This will request `userId`, and default to '' if not provided.\n  @consume userId = ''\n  // This will request `userName`, and default to '' if not provided.\n  @consume userName = ''\n\n  async handleEvent() {\n    if (confirm(`Would you like to block ${this.userName}?`)) {\n      await fetch(`/users/${userId}/delete`)\n    }\n  }\n}\n\n@controller\n@providable\nclass FollowUser extends HTMLElement {\n  // This will request `userId`, and default to '' if not provided.\n  @consume userId = ''\n  // This will request `userName`, and default to '' if not provided.\n  @consume userName = ''\n\n  async handleEvent() {\n    if (confirm(`Would you like to follow ${this.userName}?`)) {\n      await fetch(`/users/${userId}/delete`)\n    }\n  }\n}\n\n@controller\n@providable\nclass UserRow extends HTMLElement {\n    // This will provide `userId` as '123' to any nested children that request it.\n    @provide userId = '123'\n    // This will provide `userName` as 'Alex' to any nested children that request it.\n    @provide userName = 'Alex'\n}\n```\n\n```html\n<user-row>\n  <follow-user><button data-action=\"click:follow-user\"></follow-user>\n  <block-user><button data-action=\"click:block-user\"></block-user>\n</user-row>\n```\n\n### Combining Providables with Attributes\n\nThis shows how the basic pattern works, but `UserRow` having fixed strings isn't very useful. The `@provide` decorator can be combined with other decorators to make it more powerful, for example `@attr`:\n\n```typescript\nimport {providable, consume, provide, @attr, controller} from '@github/catalyst'\n\n@controller\n@providable\nclass UserRow extends HTMLElement {\n  @provide @attr userId = ''\n  @provide @attr userName = ''\n}\n```\n```html\n<user-row user-id=\"123\" user-name=\"Alex\">\n  <follow-user><button data-action=\"click:follow-user\"></follow-user>\n  <block-user><button data-action=\"click:block-user\"></block-user>\n</user-row>\n<user-row user-id=\"864\" user-name=\"Riley\">\n  <follow-user><button data-action=\"click:follow-user\"></follow-user>\n  <block-user><button data-action=\"click:block-user\"></block-user>\n</user-row>\n```\n\n### Providing advanced values\n\nValues aren't just limited to strings, they can be any type; for example functions, classes, or even other controllers! We could implement a custom dialog component which exists as a sibling and invoke it using providers and `@target`:\n\n\n```typescript\nimport {providable, consume, provide, target, attr, controller} from '@github/catalyst'\n\n@controller\n@providable\nclass UserList extends HTMLElement {\n  @provide @target dialog: UserDialogElement\n}\n\n@controller\nclass UserDialog extends HTMLElement {\n  setTitle(title: string) {\n    this.title.textContent = title\n  }\n  confirm() {\n    this.show()\n    return this.untilClosed()\n  }\n  //...\n}\n\n@controller\n@providable\nclass FollowUser extends HTMLElement {\n  // This will request `userId`, and default to '' if not provided.\n  @consume userId = ''\n  // This will request `userName`, and default to '' if not provided.\n  @consume userName = ''\n  // This will request `dialog`, defaulting it to `null` if not provided:\n  @consume dialog: UserDialog | null = null\n\n  async handleEvent() {\n    if (!this.dialog) return\n    this.dialog.setTitle(`Would you like to follow ${this.userName}?`)\n    if (await this.dialog.confirm()) {\n      await fetch(`/users/${this.userId}/delete`)\n    }\n  }\n}\n```\n```html\n<user-list>\n  <user-row user-id=\"123\" user-name=\"Alex\">\n    <follow-user><button data-action=\"click:follow-user\"></follow-user>\n    <block-user><button data-action=\"click:block-user\"></block-user>\n  </user-row>\n  <user-row user-id=\"864\" user-name=\"Riley\">\n    <follow-user><button data-action=\"click:follow-user\"></follow-user>\n    <block-user><button data-action=\"click:block-user\"></block-user>\n  </user-row>\n\n  <user-dialog data-target=\"user-list.dialog\"><!-- ... --></user-dialog>\n\n</user-list>\n```\n\n### Asynchronous Providers\n\nSometimes you might want to have a provider do some asynchronous work - such as fetch some data over the network, and only provide the fully resolved value. In this case you can use the `@provideAsync` decorator. This decorator resolves the value before giving it to the consumer, so the consumer never deals with the Promise!\n\n```ts\nimport {providable, consume, provideAsync, target, attr, controller} from '@github/catalyst'\n\n@controller\n@providable\nclass ServerState extends HTMLElement {\n  @provideAsync get hitCount(): Promise<number> {\n    return (async () => {\n      const res = await fetch('/hitcount')\n      const json = await res.json()\n      return json.hits\n    })()\n  }\n}\n\n@controller\nclass HitCount extends HTMLElement {\n  @consume set hitCount(count: number) {\n    this.innerHTML = html`${count} hits!`\n  }\n}\n```\n```html\n<server-state>\n  <hit-count>\n    Loading...\n  </hit-count>\n</server-state>\n```\n\nIf you're interested to find out how the Provider pattern works, you can look at the [context community-protocol as part of webcomponents-cg](https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md).\n"
  },
  {
    "path": "docs/_guide/rendering-2.md",
    "content": "---\nversion: 2\nchapter: 11\ntitle: Rendering\nsubtitle: Rendering HTML subtrees\npermalink: /guide-v2/rendering\n---\n\nSometimes it's necessary to render an HTML subtree as part of a component. This can be especially useful if a component is driving complex UI that is only interactive with JS.\n\n{% capture callout %}\nRemember to _always_ make your JavaScript progressively enhanced, where possible. Using JS to render large portions of the UI, that could be rendered server-side is an anti-pattern; it can be difficult for users to interact with - especially users who disable JS, or when JS fails to load, or those using assistive technologies. Rendering on the client can also impact the [CLS Web Vital](https://web.dev/cls/).\n{% endcapture %}{% include callout.md %}\n\nBy leveraging the native [`ShadowDOM`](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) feature, Catalyst components can render complex sub-trees, fully encapsulated from the rest of the page.\n\n[Actions]({{ site.baseurl }}/guide/actions) and [Targets]({{ site.baseurl }}/guide/targets) all work within an elements ShadowRoot.\n\nYou can also leverage the [declarative shadow DOM](https://web.dev/declarative-shadow-dom/) and render a template inline to your HTML, which will automatically be attached (this may require a polyfill for browsers which are yet to support this feature).\n\n### Example\n\n```html\n<hello-world>\n  <template shadowroot=\"open\">\n    <p>\n      Hello <span data-target=\"hello-world.nameEl\">World</span>\n    </p>\n  </template>\n</hello-world>\n```\n```typescript\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target nameEl: HTMLElement\n  get name() {\n    return this.nameEl.textContent\n  }\n  set name(value: string) {\n    this.nameEl.textContent = value\n  }\n}\n```\n\n{% capture callout %}\nRemember that _all_ instances of your controller _must_ add the `<template shadowroot>` HTML. If an instance does not have the `<template data-shadowroot>` as a direct child, then the shadow DOM won't be rendered for it!\n{% endcapture %}{% include callout.md %}\n\n\nIt is also possible to attach a shadowRoot to your element during the `connectedCallback`, like so:\n\n```typescript\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target nameEl: HTMLElement\n  get name() {\n    return this.nameEl.textContent\n  }\n  set name(value: string) {\n    this.nameEl.textContent = value\n  }\n\n  connectedCallback() {\n    this.attachShadow({ mode: 'open' }).innerHTML = `<p>\n      Hello <span data-target=\"hello-world.nameEl\">World</span>\n    </p>`\n  }\n}\n```\n\n### Updating a Template element using JS templates\n\nSometimes you wont have a template that is server rendered, and instead want to make a template using JS. Catalyst does not support this out of the box, but it is possible to use another library: `@github/jtml`. This library can be used to write declarative templates using JS. Let's re-work the above example using `@github/jtml`:\n\n```typescript\nimport { attr, controller } from \"@github/catalyst\"\nimport { html, render } from \"@github/jtml\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr name = 'World'\n\n  connectedCallback() {\n    this.attachShadow({mode: 'open'})\n  }\n\n  attributeChangedCallback() {\n    render(html`\n      <div>\n        Hello <span>${ this.name }</span>\n      </div>`,\n    this.shadowRoot!)\n  }\n}\n```\n\nHere, instead of declaring our template in HTML, we can do so in JS, and achieve exactly the same effect. We aren't using `@targets` in this example, as there is a more direct way to handle the data; relying on `attributeChangedCallback` which will efficiently update only the parts that change.\n\nThe same effect could be achieved without using `@attr` via:\n\n```typescript\nimport { controller } from \"@github/catalyst\"\nimport { html, render } from \"@github/jtml\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n\n  // Make `name` automatically update when changed\n  #name = 'World'\n  get name() {\n    return this.#name\n  }\n  set name(value: string) {\n    this.#name = value\n    this.update()\n  }\n\n  connectedCallback() {\n    this.attachShadow({mode: 'open'})\n    this.update()\n  }\n\n  update() {\n    render(html`\n      <div>\n        Hello <span>${ this.#name }</span>\n      </div>`,\n    this.shadowRoot!)\n  }\n}\n```\n\n"
  },
  {
    "path": "docs/_guide/rendering.md",
    "content": "---\nversion: 1\nchapter: 8\ntitle: Rendering\nsubtitle: Rendering HTML subtrees\n---\n\nSometimes it's necessary to render an HTML subtree as part of a component. This can be especially useful if a component is driving complex UI that is only interactive with JS.\n\n{% capture callout %}\nRemember to _always_ make your JavaScript progressively enhanced, where possible. Using JS to render large portions of the UI, that could be rendered server-side is an anti-pattern; it can be difficult for users to interact with - especially users who disable JS, or when JS fails to load, or those using assistive technologies. Rendering on the client can also impact the [CLS Web Vital](https://web.dev/cls/).\n{% endcapture %}{% include callout.md %}\n\nBy leveraging the native [`ShadowDOM`](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) feature, Catalyst components can render complex sub-trees, fully encapsulated from the rest of the page.\n\nCatalyst will automatically look for elements that match the `template[data-shadowroot]` selector, within your controller. If it finds one as a direct-child of your controller, it will use that to create a shadowRoot. \n\nCatalyst Controllers will search for a direct child of `template[data-shadowroot]` and load its contents as the `shadowRoot` of the element. [Actions]({{ site.baseurl }}/guide/actions) and [Targets]({{ site.baseurl }}/guide/targets) all work within an elements ShadowRoot.\n\n### Example\n\n```html\n<hello-world>\n  <template data-shadowroot>\n    <p>\n      Hello <span data-target=\"hello-world.nameEl\">World</span>\n    </p>\n  </template>\n</hello-world>\n```\n```typescript\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target nameEl: HTMLElement\n  get name() {\n    return this.nameEl.textContent\n  }\n  set name(value: string) {\n    this.nameEl.textContent = value\n  }\n}\n```\n\nProviding the `<template data-shadowroot>` element as a direct child of the `hello-world` element tells Catalyst to render the templates contents automatically, and so all `HelloWorldElements` with this template will be rendered with the contents.\n\n{% capture callout %}\nRemember that _all_ instances of your controller _must_ add the `<template data-shadowroot>` HTML. If an instance does not have the `<template data-shadowroot>` as a direct child, then the shadow DOM won't be rendered for it!\n{% endcapture %}{% include callout.md %}\n\n### Updating a Template element using JS templates\n\nSometimes you wont have a template that is server rendered, and instead want to make a template using JS. Catalyst does not support this out of the box, but it is possible to use another library: `@github/jtml`. This library can be used to write declarative templates using JS. Let's re-work the above example using `@github/jtml`:\n\n```typescript\nimport { attr, controller } from \"@github/catalyst\"\nimport { html, render } from \"@github/jtml\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @attr name = 'World'\n\n  connectedCallback() {\n    this.attachShadow({mode: 'open'})\n  }\n\n  attributeChangedCallback() {\n    render(html`\n      <div>\n        Hello <span>${ this.name }</span>\n      </div>`,\n    this.shadowRoot!)\n  }\n}\n```\n\nHere, instead of declaring our template in HTML, we can do so in JS, and achieve exactly the same effect. We aren't using `@targets` in this example, as there is a more direct way to handle the data; relying on `attributeChangedCallback` which will efficiently update only the parts that change.\n\nThe same effect could be achieved without using `@attr` via:\n\n```typescript\nimport { controller } from \"@github/catalyst\"\nimport { html, render } from \"@github/jtml\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n\n  // Make `name` automatically update when changed\n  #name = 'World'\n  get name() {\n    return this.#name\n  }\n  set name(value: string) {\n    this.#name = value\n    this.update()\n  }\n\n  connectedCallback() {\n    this.attachShadow({mode: 'open'})\n    this.update()\n  }\n\n  update() {\n    render(html`\n      <div>\n        Hello <span>${ this.#name }</span>\n      </div>`,\n    this.shadowRoot!)\n  }\n}\n```\n"
  },
  {
    "path": "docs/_guide/targets-2.md",
    "content": "---\nversion: 2\nchapter: 5\ntitle: Targetable\nsubtitle: Querying Descendants\npermalink: /guide-v2/targets\n---\n\nOne of the three [core patterns]({{ site.baseurl }}/guide/introduction#three-core-concepts-observe-listen-query) is Querying. In Catalyst, Targets are the preferred way to query. Targets use `querySelector` under the hood, but in a way that makes it a lot simpler to work with.\n\nCatalyst Components are really just Web Components, so you could use `querySelector` or `querySelectorAll` to select descendants of the element. Targets avoid some of the problems of `querySelector`; they provide a more consistent interface, avoid coupling CSS classes or HTML tag names to JS, and they handle subtle issues like nested components. Targets are also a little more ergonomic to reuse in a class. We'd recommend using Targets over `querySelector` wherever you can.\n\nTo create a Target, use the `@target` decorator on a class field, and add the matching `data-target` attribute to your HTML, like so:\n\n### Example\n\n<div class=\"d-flex my-4\">\n  <div>\n<!-- annotations\ndata-target \".*\": This maps to the `@target output` property\n-->\n\n```html\n<hello-world>\n  <span\n    data-target=\"hello-world.output\">\n  </span>\n</hello-world>\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n<!-- annotations\n@ target output: This maps to the data-target attribute\n-->\n\n```js\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target output: HTMLElement\n\n  greet() {\n    this.output.textContent = `Hello, world!`\n  }\n}\n```\n\n  </div>\n</div>\n\n### Target Syntax\n\nThe target syntax follows a pattern of `controller.target`.\n\n - `controller` must be the name of a controller ascendant to the element.\n - `target` must be the name matching that of a `@target` (or `@targets`) annotated field within the Controller code.\n\n### Multiple Targets\n\n{% capture callout %} \nRemember! There are two decorators available, `@target` which fetches only one `data-target` element, and `@targets` which fetches multiple `data-targets` elements!\n{% endcapture %}{% include callout.md %}\n\nThe `@target` decorator will only ever return _one_ element, just like `querySelector`. If you want to get multiple Targets, you need the `@targets` decorator which works almost the same, but returns an Array of elements, and it searches the `data-targets` attribute (not `data-target`). \n\nElements can be referenced as multiple targets, and targets may be referenced multiple times within the HTML:\n\n<!-- annotations\ndata-targets \".*users\": This maps to the `@targets users` property\ndata-target \".*read\": This maps to the `@target read` property\ndata-target \".*write\": This maps to the `@target write` property\n-->\n\n```html\n<team-members>\n  <user-list>\n    <user-settings data-targets=\"user-list.users\">\n      <input type=\"checkbox\" data-target=\"user-settings.read\">\n      <input type=\"checkbox\" data-target=\"user-settings.write\">\n    </user-settings>\n    <user-settings data-targets=\"user-list.users\">\n      <input type=\"checkbox\" data-target=\"user-settings.read\">\n      <input type=\"checkbox\" data-target=\"user-settings.write\">\n    </user-settings>\n  </user-list>\n</team-members>\n```\n\n<br>\n\n<!-- annotations\n@ targets users: This maps to the data-targets attribute\n@ target read: This maps to the data-target attribute\n@ target write: This maps to the data-target attribute\n-->\n\n```js\nimport { controller, target, targets } from \"@github/catalyst\"\n\n@controller\nclass UserSettingsElement extends HTMLElement {\n  @target read: HTMLInputElement\n  @target write: HTMLInputElement\n\n  valid() {\n    // At least one checkbox must be checked!\n    return this.read.checked || this.write.checked\n  }\n}\n\n@controller\nclass UserListElement extends HTMLElement {\n  @targets users: HTMLElement[]\n\n  valid() {\n    // Every user must be valid!\n    return this.users.every(user => user.valid())\n  }\n}\n```\n\n### Target Vs Targets\n\nTo clarify the difference between `@target` and `@targets` here is a handy table:\n\n| Decorator  | Equivalent Native Method | Selector           | Returns          | \n|:-----------|:-------------------------|:-------------------|:-----------------|\n| `@target`  | `querySelector`          | `data-target=\"*\"`  | `Element`        | \n| `@targets` | `querySelectorAll`       | `data-targets=\"*\"` | `Array<Element>` | \n\n### Targets and \"ShadowRoots\"\n\nCustom elements can create encapsulated DOM trees known as \"Shadow\" DOM. Catalyst targets support Shadow DOM by traversing the `shadowRoot` first, if present.\n\nImportant to note here is that nodes from the `shadowRoot` get returned _first_. So `@targets` will return an array of nodes, where shadowRoot nodes are at the start of the Array, and `@target` will return a ShadowRoot target if it exists, otherwise it will fall back to traversing the elements direct children.\n\n### What about without Decorators?\n\nIf you're not using decorators, then the `@target` and `@targets` decorators have an escape hatch: you can define a static class field using the `[target.static]` computed property, as an array of key names. Like so:\n\n```js\nimport {controller, target, targets} from '@github/catalyst'\n\ncontroller(class HelloWorldElement extends HTMLElement {\n  // The same as `@target output`\n  static [target.static] = ['output']\n\n  // The same as `@targets pages; @targets links`\n  static [targets.static] = ['pages', 'links']\n\n})\n```\n\nThis is functionally identical to:\n\n```js\nimport {controller} from '@github/catalyst'\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target output\n\n  @targets pages\n  @targets links\n\n}\n```\n"
  },
  {
    "path": "docs/_guide/targets.md",
    "content": "---\nversion: 1\nchapter: 4\ntitle: Targets\nsubtitle: Querying Descendants\n---\n\nOne of the three [core patterns]({{ site.baseurl }}/guide/introduction#three-core-concepts-observe-listen-query) is Querying. In Catalyst, Targets are the preferred way to query. Targets use `querySelector` under the hood, but in a way that makes it a lot simpler to work with.\n\nCatalyst Components are really just Web Components, so you could use `querySelector` or `querySelectorAll` to select descendants of the element. Targets avoid some of the problems of `querySelector`; they provide a more consistent interface, avoid coupling CSS classes or HTML tag names to JS, and they handle subtle issues like nested components. Targets are also a little more ergonomic to reuse in a class. We'd recommend using Targets over `querySelector` wherever you can.\n\nTo create a Target, use the `@target` decorator on a class field, and add the matching `data-target` attribute to your HTML, like so:\n\n### Example\n\n<div class=\"d-flex my-4\">\n  <div>\n<!-- annotations\ndata-target \".*\": This maps to the `@target output` property\n-->\n\n```html\n<hello-world>\n  <span\n    data-target=\"hello-world.output\">\n  </span>\n</hello-world>\n```\n\n  </div>\n  <div class=\"ml-4\">\n\n<!-- annotations\n@ target output: This maps to the data-target attribute\n-->\n\n```js\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target output: HTMLElement\n\n  greet() {\n    this.output.textContent = `Hello, world!`\n  }\n}\n```\n\n  </div>\n</div>\n\n### Target Syntax\n\nThe target syntax follows a pattern of `controller.target`.\n\n - `controller` must be the name of a controller ascendant to the element.\n - `.` is the required delimiter between `controller` and `target`.\n - `target` must be the name matching that of a `@target` (or `@targets`) annotated field within the Controller code.\n\n### Multiple Targets\n\n{% capture callout %} \nRemember! There are two decorators available, `@target` which fetches only one `data-target` element, and `@targets` which fetches multiple `data-targets` elements!\n{% endcapture %}{% include callout.md %}\n\nThe `@target` decorator will only ever return _one_ element, just like `querySelector`. If you want to get multiple Targets, you need the `@targets` decorator which works almost the same, but returns an Array of elements, and it searches the `data-targets` attribute (not `data-target`). \n\nElements can be referenced as multiple targets, and targets may be referenced multiple times within the HTML:\n\n<!-- annotations\ndata-targets \".*users\": This maps to the `@targets users` property\ndata-target \".*read\": This maps to the `@target read` property\ndata-target \".*write\": This maps to the `@target write` property\n-->\n\n```html\n<team-members>\n  <user-list>\n    <user-settings data-targets=\"user-list.users\">\n      <input type=\"checkbox\" data-target=\"user-settings.read\">\n      <input type=\"checkbox\" data-target=\"user-settings.write\">\n    </user-settings>\n    <user-settings data-targets=\"user-list.users\">\n      <input type=\"checkbox\" data-target=\"user-settings.read\">\n      <input type=\"checkbox\" data-target=\"user-settings.write\">\n    </user-settings>\n  </user-list>\n</team-members>\n```\n\n<br>\n\n<!-- annotations\n@ targets users: This maps to the data-targets attribute\n@ target read: This maps to the data-target attribute\n@ target write: This maps to the data-target attribute\n-->\n\n```js\nimport { controller, target, targets } from \"@github/catalyst\"\n\n@controller\nclass UserSettingsElement extends HTMLElement {\n  @target read: HTMLInputElement\n  @target write: HTMLInputElement\n\n  valid() {\n    // At least one checkbox must be checked!\n    return this.read.checked || this.write.checked\n  }\n}\n\n@controller\nclass UserListElement extends HTMLElement {\n  @targets users: HTMLElement[]\n\n  valid() {\n    // Every user must be valid!\n    return this.users.every(user => user.valid())\n  }\n}\n```\n\n### Target Vs Targets\n\nTo clarify the difference between `@target` and `@targets` here is a handy table:\n\n| Decorator  | Equivalent Native Method | Selector           | Returns          | \n|:-----------|:-------------------------|:-------------------|:-----------------|\n| `@target`  | `querySelector`          | `data-target=\"*\"`  | `Element`        | \n| `@targets` | `querySelectorAll`       | `data-targets=\"*\"` | `Array<Element>` | \n\n### Targets and \"ShadowRoots\"\n\nCustom elements can create encapsulated DOM trees known as \"Shadow\" DOM. Catalyst targets support Shadow DOM by traversing the `shadowRoot` first, if present.\n\nImportant to note here is that nodes from the `shadowRoot` get returned _first_. So `@targets` will return an array of nodes, where shadowRoot nodes are at the start of the Array, and `@target` will return a ShadowRoot target if it exists, otherwise it will fall back to traversing the elements direct children.\n\n### What about without Decorators?\n\nIf you're using decorators, then the `@target` and `@targets` decorators will turn the decorated properties into getters.\n\nIf you're not using decorators, then you'll need to make a `getter`, and call `findTarget(this, key)` or `findTargets(this, key)` in the getter, for example:\n\n```js\nimport {findTarget, findTargets} from '@github/catalyst'\nclass HelloWorldElement extends HTMLElement {\n\n  get output() {\n    return findTarget(this, 'output')\n  }\n\n  get pages() {\n    return findTargets(this, 'pages')\n  }\n\n}\n```\n"
  },
  {
    "path": "docs/_guide/testing-2.md",
    "content": "---\nversion: 2\nchapter: 13\ntitle: Testing\nsubtitle: Tips for automated testing\npermalink: /guide-v2/testing\n---\n\nCatalyst controllers are based on Web Components, and as such need the Web Platform environment to run in, including in tests. It's possible to run these tests in \"browser like\" environments such as NodeJS or Deno with libraries like jsdom, but it's best to run tests directly in the browser.\n\n### Recommended Libraries\n\nWe recommend using [`@web/test-runner`](https://modern-web.dev/docs/test-runner/overview/), which provides the `web-test-runner` command line tool that can run [mocha](https://mochajs.org/) test files in a headless Chromium instance. We also recommend using [`@open-wc/testing`](https://open-wc.org/docs/testing/testing-package/) which provides a set of testing functions, including `expect` from [Chai](https://www.chaijs.com/api/bdd/). If you're using TypeScript, it may be worth also installing [`@web/dev-server-esbuild`](https://modern-web.dev/docs/dev-server/overview/) which can transpile TypeScript to JavaScript, allowing the use of TypeScript within test files themselves.\n\nWith these installed and configured your `package.json` might look something like:\n\n```json\n{\n  \"name\": \"my-catalyst-component\",\n  \"scripts\": {\n    \"test\": \"web-test-server\"\n  },\n  \"devDependencies\": {\n    \"@web/dev-server-esbuild\": \"^0.3.0\",\n    \"@web/test-runner\": \"^0.13.27\",\n    \"@open-wc/testing\": \"^3.1.2\"\n  }\n}\n```\n\nYou can configure the `web-test-server` by writing a `web-test-runner.config.js` file, which sets up the esbuild plugin to transpile TypeScript, and configure the directory containing your test files: \n\n```typescript\nimport {esbuildPlugin} from '@web/dev-server-esbuild'\n\nexport default {\n  files: ['test/*'],\n  nodeResolve: true,\n  plugins: [esbuildPlugin({ts: true})]\n}\n```\n\n#### Example Test File\n\nWith this set-up, the boilerplate for an Element test suite might look something like this:\n\n```typescript\n// test/my-controller.ts\nimport {expect, fixture, html} from '@open-wc/testing'\nimport {MyController} from '../src/my-controller'\n\ndescribe('MyController', () => {\n  let instance\n  beforeEach(async () => {\n    instance = await fixture(html`<my-controller>\n      <div class=\"expected-children\"></div>\n    </my-controller>`)\n  })\n\n  it('is a Catalyst controller', () => {\n    expect(instance).to.have.attribute('data-catalyst')\n  })\n  \n  it('matches snapshot', () => {\n    expect(instance).dom.to.equalSnapshot()\n  })\n  \n  it('passes Axe tests', () => \n    expect(instance).to.be.accessible()\n  })\n  \n  it('...') // Fill out the rest\n})\n```\n\n##### Useful Assertions\n\nThe `@open-wc/testing` package exports the `expect` function from Chai, but also automatically registers a set of plugins useful for writing web components, including [chai-a11y-axe](https://www.npmjs.com/package/chai-a11y-axe) and [chai-dom](https://www.npmjs.com/package/chai-dom). Here are some handy example assertions which may be commonly written:\n\n\n- `expect(instance).to.be.accessible()` - Runs a suite of [Axe](https://www.npmjs.com/package/axe) accessibility tests on the element.\n- `expect(instance).dom.to.equalSnapshot()` - Stores a snaphsot test of the existing DOM, which can be tested against later, for regressions.\n- `expect(instance).shadowDom.to.equalSnapshot()` - Stores a snaphsot test of the existing ShadowDOM, which can be tested against later, for regressions.\n- `expect(instance).to.have.class('foo')` - Checks the element has the `foo` class (like `el.classList.contains('foo')`).\n- `expect(instance).to.have.attribute('foo')` - Checks the element has the `foo` attribute (like `el.hasAttribute('foo')`).\n- `expect(instance).to.have.attribute('foo')` - Checks the element has the `foo` attribute (like `el.hasAttribute('foo')`).\n- `expect(instance).to.have.descendants('.foo')` - Checks the element has elements matching the selector `.foo` attribute (like `el.querySelectorAll('foo')`).\n\n"
  },
  {
    "path": "docs/_guide/testing.md",
    "content": "---\nversion: 1\nchapter: 14\ntitle: Testing\nsubtitle: Tips for automated testing\n---\n\nCatalyst controllers are based on Web Components, and as such need the Web Platform environment to run in, including in tests. It's possible to run these tests in \"browser like\" environments such as NodeJS or Deno with libraries like jsdom, but it's best to run tests directly in the browser.\n\n### Recommended Libraries\n\nWe recommend using [`@web/test-runner`](https://modern-web.dev/docs/test-runner/overview/), which provides the `web-test-runner` command line tool that can run [mocha](https://mochajs.org/) test files in a headless Chromium instance. We also recommend using [`@open-wc/testing`](https://open-wc.org/docs/testing/testing-package/) which provides a set of testing functions, including `expect` from [Chai](https://www.chaijs.com/api/bdd/). If you're using TypeScript, it may be worth also installing [`@web/dev-server-esbuild`](https://modern-web.dev/docs/dev-server/overview/) which can transpile TypeScript to JavaScript, allowing the use of TypeScript within test files themselves.\n\nWith these installed and configured your `package.json` might look something like:\n\n```json\n{\n  \"name\": \"my-catalyst-component\",\n  \"scripts\": {\n    \"test\": \"web-test-server\"\n  },\n  \"devDependencies\": {\n    \"@web/dev-server-esbuild\": \"^0.3.0\",\n    \"@web/test-runner\": \"^0.13.27\",\n    \"@open-wc/testing\": \"^3.1.2\"\n  }\n}\n```\n\nYou can configure the `web-test-server` by writing a `web-test-runner.config.js` file, which sets up the esbuild plugin to transpile TypeScript, and configure the directory containing your test files: \n\n```typescript\nimport {esbuildPlugin} from '@web/dev-server-esbuild'\n\nexport default {\n  files: ['test/*'],\n  nodeResolve: true,\n  plugins: [esbuildPlugin({ts: true})]\n}\n```\n\n#### Example Test File\n\nWith this set-up, the boilerplate for an Element test suite might look something like this:\n\n```typescript\n// test/my-controller.ts\nimport {expect, fixture, html} from '@open-wc/testing'\nimport {MyController} from '../src/my-controller'\n\ndescribe('MyController', () => {\n  let instance\n  beforeEach(async () => {\n    instance = await fixture(html`<my-controller>\n      <div class=\"expected-children\"></div>\n    </my-controller>`)\n  })\n\n  it('is a Catalyst controller', () => {\n    expect(instance).to.have.attribute('data-catalyst')\n  })\n  \n  it('matches snapshot', () => {\n    expect(instance).dom.to.equalSnapshot()\n  })\n  \n  it('passes Axe tests', () => \n    expect(instance).to.be.accessible()\n  })\n  \n  it('...') // Fill out the rest\n})\n```\n\n##### Useful Assertions\n\nThe `@open-wc/testing` package exports the `expect` function from Chai, but also automatically registers a set of plugins useful for writing web components, including [chai-a11y-axe](https://www.npmjs.com/package/chai-a11y-axe) and [chai-dom](https://www.npmjs.com/package/chai-dom). Here are some handy example assertions which may be commonly written:\n\n\n- `expect(instance).to.be.accessible()` - Runs a suite of [Axe](https://www.npmjs.com/package/axe) accessibility tests on the element.\n- `expect(instance).dom.to.equalSnapshot()` - Stores a snaphsot test of the existing DOM, which can be tested against later, for regressions.\n- `expect(instance).shadowDom.to.equalSnapshot()` - Stores a snaphsot test of the existing ShadowDOM, which can be tested against later, for regressions.\n- `expect(instance).to.have.class('foo')` - Checks the element has the `foo` class (like `el.classList.contains('foo')`).\n- `expect(instance).to.have.attribute('foo')` - Checks the element has the `foo` attribute (like `el.hasAttribute('foo')`).\n- `expect(instance).to.have.attribute('foo')` - Checks the element has the `foo` attribute (like `el.hasAttribute('foo')`).\n- `expect(instance).to.have.descendants('.foo')` - Checks the element has elements matching the selector `.foo` attribute (like `el.querySelectorAll('foo')`).\n\n"
  },
  {
    "path": "docs/_guide/you-will-need.md",
    "content": "---\nversion: 1\nchapter: 2\nsubtitle: How to install and set up Catalyst\n---\n\nCatalyst is available as an npm module `@github/catalyst`. To install into your project, use the command `npm install @github/catalyst`. \n\n### TypeScript\n\nCatalyst has no strict dependencies, but it relies on TypeScript for decorator support, so you should also configure your project to use TypeScript. [Read the TypeScript docs on how to set up TypeScript on a new project](https://www.typescriptlang.org/docs/home.html).\n\n### Polyfills\n\nCatalyst uses modern browser standards, and so requires evergreen browsers or may require polyfilling native functionality in older browsers. You'll need to ensure the following features are available:\n\n - [`toggleAttribute`](https://caniuse.com/#search=toggleAttribute). [`mdn-polyfills`](https://github.com/msn0/mdn-polyfills) or [`dom4`](https://github.com/WebReflection/dom4) libraries can polyfill this.\n - [`window.customElements`](https://caniuse.com/#search=customElements). [`@webcomponents/custom-elements`](https://github.com/webcomponents/polyfills/tree/master/packages/custom-elements) can polyfill this.\n - [`MutationObserver`](https://caniuse.com/#search=MutationObserver). [`mutation-observer`](https://github.com/webmodules/mutation-observer) can polyfill this.\n\nPlease note this list may increase over time. Catalyst will never ship with polyfills that add missing browser functionality, but will continue to use the latest Web Standards, and so may require more polyfills as new releases come out.\n\n### Build considerations\n\nWhen using build tools, some JavaScript minifiers modify the class name that Catalyst relies on. You know you have an issue if you encounter the error `\"c\" is not a valid custom element name`.\n\nThe preferred way to handle this is to disable renaming class names in your build tools.\n\n#### ESBuild\n\nWhen using ESBuild you can turn off all class and function name minification with the [`keep_names`](https://esbuild.github.io/api/#keep-names) option. Setting this to `true` in your build will opt-out all classes and all functions from minification.\n\n\n```ts\n{ keep_names: true }\n// Or --keep-names on the CLI\n```\n\n#### Terser\n\nWhen using Terser you have a bit more control, and can explicitly opt just classes, or just certain class names out of minification. For example to opt-out class names that end with `Element` you can set the following config:\n\n```ts\n{ keep_classnames: /Element$/ }\n```\n\nIt is also possible to set `keep_classnames` to `true` (or pass `--keep-classnames` to the CLI tool), which will opt-out all class names. [You can read more about the minification options on Terser's docs](https://terser.org/docs/api-reference#minify-options)\n\n#### SWC\n\nWhen using SWC you can use the `keep_classnames` option just like Terser. As SWC also handles Transpilation, you should be sure to enable native class syntax by specifiying `target` to at least `es2016`. [Take a look at the SWC docs for more about compression options](https://swc.rs/docs/configuration/minification#jscminifycompress).\n\n```json\n{\n  \"jsc\": {\n    \"target\": \"es2016\",\n    \"minify\": {\n      \"compress\": {\n        \"keep_classnames\": true\n      }\n    }\n  }\n}\n```\n\n#### Other alternatives\n\nIf your tool chain does not support opting out of minification, or if you would prefer to keep name minification on, you can instead selectively re-assign the `name` field to Catalyst controllers:\n\n```ts\n@controller\nclass UserList extends HTMLElement {\n  static name = 'UserList'\n}\n```\n\nTypeScript will need the `useDefineForClassFields` set to `true` for the above to work, alternatively you can use the following syntax with `useDefineForClassFields` kept off:\n\n```ts\n@controller\nclass UserList extends HTMLElement {\n  static get name() { return 'UserList' }\n}\n```\n\nYou'll need to keep the class name either way. TypeScript decorators only support _class declarations_ which require a name between `class` and `extends`. For example the following will be a SyntaxError:\n\n```ts\n@controller\nclass extends HTMLElement { // You can't do this!\n  static name = 'UserList'\n}\n```\n\n\n"
  },
  {
    "path": "docs/_guide/your-first-component-2.md",
    "content": "---\nversion: 2\nchapter: 2\ntitle: Your First Component\nsubtitle: Building an HTMLElement\npermalink: /guide-v2/your-first-component\n---\n\n### Catalyst's `@controller` decorator\n\nCatalyst's `@controller` decorator lets you create Custom Elements with virtually no boilerplate, by automatically calling `customElements.register`, and by adding [\"Actions\"]({{ site.baseurl }}/guide/actions) and [\"Targets\"]({{ site.baseurl }}/guide/targets) features described later. Using TypeScript (with `decorators` support enabled), simply add `@controller` to the top of your class:\n\n<!-- annotations\ncontroller: This must be added to all Catalyst controllers.\nextends HTMLElement: This must be added to all Catalyst controllers.\nconnectedCallback: This runs when the element is added to the DOM | {{ site.baseurl }}/guide/lifecycle-hooks/#codeconnectedcallbackcode\n-->\n\n```js\nimport {controller} from '@github/catalyst'\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  connectedCallback() {\n    this.innerHTML = 'Hello World!'\n  }\n}\n```\n<br>\n\nCatalyst will automatically convert the classes name so the HTML tag will be `<hello-world>`. It removes the trailing `Element` suffix and lowercases all capital letters, separating them with a dash.\n\nCatalyst controllers can end in `Element`, `Controller`, or `Component` and Catalyst will remove this suffix when generating a tag name. Adding one of these suffixes is _not_ required - just convention. All examples in this guide use `Element` suffixed names (see our [convention note on this for more]({{ site.baseurl }}/guide/conventions#suffix-your-controllers-consistently-for-symmetry)).\n\n{% capture callout %}\nRemember! A class name _must_ include at least two CamelCased words (not including the `Element`, `Controller` or `Component` suffix). One-word elements will raise exceptions. Example of good names: `UserListElement`, `SubTaskController`, `PagerContainerComponent`\n{% endcapture %}{% include callout.md %}\n\n\n### What does `@controller` do?\n\nThe `@controller` decorator ties together the various other decorators within Catalyst, plus a few extra conveniences such as automatically registering the element, which saves you writing some boilerplate that you'd otherwise have to write by hand. Specifically the `@controller` decorator:\n\n - Derives a tag name based on your class name, removing the trailing `Element` suffix and lowercasing all capital letters, separating them with a dash.\n - Calls `window.customElements.define` with the newly derived tag name and your class.\n - Loads the `attrable` decorator, which provides the ability to define `@attr` decorators. See [attrs]({{ site.baseurl }}/guide/attrs) for more on this.\n - Loads the `actionable` decorator, which provides the ability to bind actions. See [actions]({{ site.baseurl }}/guide/actions) for more on this.\n - Loads the `targetable` decorator, which provides Target querying. See [targets]({{ site.baseurl }}/guide/targets) for more on this.\n \nYou can do all of this manually; for example here's the above `HelloWorldElement`, written without the `@controller` annotation:\n\n```js\nimport {attrable, targetable, actionable} from '@github/catalyst'\n\n@register\n@actionable\n@attrable\n@targetable\nclass HelloWorldElement extends HTMLElement {\n}\n```\n\nThe `@controller` decorator saves on having to write this boilerplate for each element.\n\n### What about without TypeScript Decorators?\n\nIf you don't want to use TypeScript decorators, you can use `controller` as a regular function by passing it to your class:\n\n```js\nimport {controller} from '@github/catalyst'\n\ncontroller(\n  class HelloWorldElement extends HTMLElement {\n    //...\n  }\n)\n```\n<br>\n\n"
  },
  {
    "path": "docs/_guide/your-first-component.md",
    "content": "---\nversion: 1\nchapter: 2\ntitle: Your First Component\nsubtitle: Building an HTMLElement\n---\n\n### Catalyst's `@controller` decorator\n\nCatalyst's `@controller` decorator lets you create Custom Elements with virtually no boilerplate, by automatically calling `customElements.register`, and by adding [\"Actions\"]({{ site.baseurl }}/guide/actions) and [\"Targets\"]({{ site.baseurl }}/guide/targets) features described later. Using TypeScript (with `decorators` support enabled), simply add `@controller` to the top of your class:\n\n<!-- annotations\ncontroller: This must be added to all Catalyst controllers.\nextends HTMLElement: This must be added to all Catalyst controllers.\nconnectedCallback: This runs when the element is added to the DOM | {{ site.baseurl }}/guide/lifecycle-hooks/#codeconnectedcallbackcode\n-->\n\n```js\nimport {controller} from '@github/catalyst'\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  connectedCallback() {\n    this.innerHTML = 'Hello World!'\n  }\n}\n```\n<br>\n\nCatalyst will automatically convert the classes name; removing the trailing `Element` suffix and lowercasing all capital letters, separating them with a dash.\n\nBy convention Catalyst controllers end in `Element`; Catalyst will omit this when generating a tag name. The `Element` suffix is _not_ required - just convention. All examples in this guide use `Element` suffixed names.\n\n### Custom Element Names\n\nIf you need to use a specific element name that doesn't match your class name (for example, to support minification), you can pass the element name directly to the `@controller` decorator:\n\n```js\nimport {controller} from '@github/catalyst'\n\n@controller('hello-widget')\nclass SomeClass extends HTMLElement {\n  connectedCallback() {\n    this.innerHTML = 'Hello from hello-widget!'\n  }\n}\n```\n<br>\n\nThis will register the element as `<hello-widget>` regardless of the class name. This is particularly useful when:\n- Your production build minifies class names\n- You want explicit control over the element name\n- The class name doesn't follow the naming pattern required for automatic naming\n\n{% capture callout %}\nRemember! A class name _must_ include at least two CamelCased words (not including the `Element` suffix). One-word elements will raise exceptions. Example of good names: `UserListElement`, `SubTaskElement`, `PagerContainerElement`\n{% endcapture %}{% include callout.md %}\n\n\n### What does `@controller` do?\n\nThe `@controller` decorator ties together the various other decorators within Catalyst, plus a few extra conveniences such as automatically registering the element, which saves you writing some boilerplate that you'd otherwise have to write by hand. Specifically the `@controller` decorator:\n\n - Derives a tag name based on your class name, removing the trailing `Element` suffix and lowercasing all capital letters, separating them with a dash. You can optionally provide a custom element name as a parameter (e.g., `@controller('my-element')`).\n - Calls `window.customElements.define` with the newly derived (or provided) tag name and your class.\n - Calls `defineObservedAttributes` with the class to add map any `@attr` decorators. See [attrs]({{ site.baseurl }}/guide/attrs) for more on this.\n - Injects the following code inside of the `connectedCallback()` function of your class:\n   - `bind(this)`; ensures that as your element connects it picks up any `data-action` handlers. See [actions]({{ site.baseurl }}/guide/actions) for more on this.\n   - `autoShadowRoot(this)`; ensures that your element loads any `data-shadowroot` templates. See [rendering]({{ site.baseurl }}/guide/rendering) for more on this.\n   - `initializeAttrs(this)`; ensures that your element binds any `data-*` attributes to props. See [attrs]({{ site.baseurl }}/guide/attrs) for more on this.\n \nYou can do all of this manually; for example here's the above `HelloWorldElement`, written without the `@controller` annotation:\n\n```js\nimport {bind, autoShadowRoot, initializeAttrs, defineObservedAttributes} from '@github/catalyst'\nclass HelloWorldElement extends HTMLElement {\n  connectedCallback() {\n    autoShadowRoot(this)\n    initializeAttrs(this)\n    this.innerHTML = 'Hello World!'\n    bind(this)\n  }\n}\ndefineObservedAttributes(HelloWorldElement)\nwindow.customElements.define('hello-world', HelloWorldElement)\n```\n\nThe `@controller` decorator saves on having to write this boilerplate for each element.\n\n### What about without TypeScript Decorators?\n\nIf you don't want to use TypeScript decorators, you can use `controller` as a regular function by passing it to your class:\n\n```js\nimport {controller} from '@github/catalyst'\n\ncontroller(\n  class HelloWorldElement extends HTMLElement {\n    //...\n  }\n)\n```\n\nOr with a custom element name:\n\n```js\nimport {controller} from '@github/catalyst'\n\ncontroller('my-custom-name')(\n  class HelloWorldElement extends HTMLElement {\n    //...\n  }\n)\n```\n<br>\n"
  },
  {
    "path": "docs/_includes/callout.md",
    "content": "\n<div class=\"d-flex border rounded-1 my-3 box-shadow-medium\">\n  <span class=\"d-flex flex-items-center bg-blue text-white rounded-left-1 p-3\">\n    <svg width=\"24\" height=\"24\" viewBox=\"0 0 14 16\" class=\"octicon octicon-info\" aria-hidden=\"true\">\n      <path\n        fill-rule=\"evenodd\"\n        d=\"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z\"\n      />\n    </svg>\n  </span>\n  <div class=\"p-3\">\n\n  {{ callout }}\n\n  </div>\n</div>\n"
  },
  {
    "path": "docs/_includes/reference_sidebar.html",
    "content": "<aside class=\"col-lg-3 pl-4 pt-1 pb-1 bg-gray\">\n  <nav class=\"position-sticky top-100px\">\n    <ul class=\"f3-light ml-4\">\n      {% for item in sidebarItems %}\n      <li class=\"py-1\">\n        <a href=\"#{{ item.name | slugify }}\">{{ item.name | remove: '\"' }}</a>\n      </li>\n      {% endfor %}\n    </ul>\n  </nav>\n</aside>\n"
  },
  {
    "path": "docs/_includes/sidebar.html",
    "content": "<aside class=\"sidebar position-md-sticky overflow-y-auto px-4 col-lg-3 py-4 py-md-1 mb-4 mb-md-0 pb-1 bg-gray\">\n  <label class=\"d-flex mr-4 flex-items-center\">\n    <span class=\"mr-4\">Version</span>\n    <select class=\"flex-1\" onchange=\"window.location.href = this.value\">\n      <option value=\"{{ site.baseurl }}/guide/introduction\" {% if page.version == 1 %} selected{% endif %}>v1.x.x</option>\n      <option value=\"{{ site.baseurl }}/guide-v2/introduction\" {% if page.version == 2 %} selected{% endif %}>v2.x.x</option>\n    </select>\n  </label>\n  <br>\n\n  <nav>\n    <ol class=\"f3-light ml-4\">\n      {% for item in sidebarItems %}\n      <li class=\"py-1\">\n        <a href=\"{{ site.baseurl }}{{ item.url }}\">{{ item.title || item.name }}</a>\n        {% if item.subtitle %}\n        <span class=\"d-block text-gray-light f5\">{{ item.subtitle }}</span>\n        {% endif %}\n      </li>\n      {% endfor %}\n    </ol>\n  </nav>\n</aside>\n"
  },
  {
    "path": "docs/_includes/type.html",
    "content": "{%- capture output %}\n  {%- case type.type %}\n    {%- when \"intrinsic\" %}\n      {{- }}<span class=\"o\">{{- type.name }}</span>\n    {%- when \"reference\" %}\n      {{- }}<span class=\"kc\">{{- type.name }}</span>\n    {%- when \"array\" %}\n      {%- assign type = type.elementType %}\n      {%- include type.html %}[]\n    {%- when \"union\" %}\n      {%- for type in type.types %}\n        {%- include type.html %}{% if forloop.last != true %}&nbsp;|&nbsp;{%- endif %}\n      {%- endfor %}\n    {%- when \"reflection\" %}\n      {%- assign type = type.declaration %}\n      {%- include type.html %}\n    {%- when \"typeParameter\" %}\n      {%- assign name = type.name %}\n      {%- assign type = type.constraint %}\n      {{- ''}}<span class=\"nf\">{{ name }}</span>\n    {%- else %}\n      {%- if type.signatures %}\n        {%- assign rootType = type %}\n        {%- for signature in type.signatures %}\n          {%- if signature.name != \"__call\" %}<span class=\"nf\">{{ signature.name }}</span>{% endif %}\n          {{- ''}}<span class=\"p\">(</span>\n          {%- for parameter in signature.parameters %}\n            {{- ''}}<span class=\"nx\">{%- if parameter.flags.isRest %}...{% endif %}{{ parameter.name }}</span><span class=\"p\">:</span>&nbsp;\n            {%- assign type = parameter.type %}\n            {%- include type.html %}\n            {%- if forloop.last != true %}<span class=\"p\">,</span>&nbsp;{%- endif %}\n          {%- endfor %}\n          {{-''}}<span class=\"p\">)</span>\n          {%- if rootType.name == \"__type\" %}&nbsp;<span class=\"p\">=&gt;</span>&nbsp;\n          {%- else %}<span class=\"p\">:</span>&nbsp;{% endif %}\n          {%- assign type = signature.type %}\n          {%- include type.html %}\n        {%- endfor %}\n      {%- else %}\n      <pre>{{- type | jsonify }}</pre>\n      {%- endif %}\n  {%- endcase %}\n{%- endcapture %}{{- output | strip_newlines }}\n"
  },
  {
    "path": "docs/_layouts/default.html",
    "content": "---\n---\n<!DOCTYPE html>\n<html lang=\"en\" class=\"height-full\">\n  <head>\n    <title>{% if page.title %}{{ page.title }} - {% endif %}{{ site.title }}</title>\n    <meta name=\"description\" content=\"Catalyst is a set of patterns and techniques for developing components within a complex application.\">\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <meta name=\"supported-color-schemes\" content=\"light dark\">\n    <link rel=\"stylesheet\" href=\"{{ site.baseurl }}/primer.css\">\n    <link rel=\"stylesheet\" href=\"{{ site.baseurl }}/github-syntax.css\">\n    <link rel=\"stylesheet\" href=\"{{ site.baseurl }}/custom.css\">\n    <link rel=\"apple-touch-icon\" sizes=\"48x48\" href=\"{{ site.baseurl }}/icons/icon-48x48.png\">\n    <link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"{{ site.baseurl }}/icons/icon-72x72.png\">\n    <link rel=\"apple-touch-icon\" sizes=\"96x96\" href=\"{{ site.baseurl }}/icons/icon-96x96.png\">\n    <link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"{{ site.baseurl }}/icons/icon-144x144.png\">\n    <link rel=\"apple-touch-icon\" sizes=\"192x192\" href=\"{{ site.baseurl }}/icons/icon-192x192.png\">\n    <link rel=\"apple-touch-icon\" sizes=\"256x256\" href=\"{{ site.baseurl }}/icons/icon-256x256.png\">\n    <link rel=\"apple-touch-icon\" sizes=\"384x384\" href=\"{{ site.baseurl }}/icons/icon-384x384.png\">\n    <link rel=\"apple-touch-icon\" sizes=\"512x512\" href=\"{{ site.baseurl }}/icons/icon-512x512.png?\">\n    <link rel=\"icon\" href=\"{{ site.baseurl }}/icons/icon-48x48.png\">\n  </head>\n  <body class=\"d-flex flex-column min-height-full\">\n    <header class=\"d-flex position-md-sticky top-0 d-md-flex main-header\">\n      <div class=\"logo flex-1 pl-3 pb-6 col-md-3 {% if page.layout != \"default\" %}bg-gray{% endif %}\">\n        <h1 class=\"m-0 mt-md-2\">Catalyst</h1>\n      </div>\n      <nav class=\"f3 mr-4 mr-md-0 col-md-9 d-flex flex-justify-center flex-md-justify-end\">\n        <ul class=\"d-flex list-style-none mr-md-6\">\n          <li class=\"ml-3 mt-3 mb-3\">\n            <a href=\"{{ site.baseurl }}/\">\n              Home\n            </a>\n          </li>\n          <li class=\"ml-3 mt-3 mb-3\">\n            <a href=\"{{ site.baseurl }}/guide/introduction\">\n              Guide\n            </a>\n          </li>\n          <li class=\"ml-3 mt-3 mb-3\">\n            <a href=\"https://github.com/github/catalyst\">\n              Source Code\n            </a>\n          </li>\n        </ul>\n      </nav>\n    </header>\n\n    {{ content }}\n\n    <script async src=\"{{ site.baseurl }}/index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/_layouts/guide.html",
    "content": "---\nlayout: default\n---\n\n{% assign sidebarItems = site.guide | where_exp: \"item\", \"item.version == page.version\" | sort: 'chapter' %}\n\n{% for item in sidebarItems  %}\n  {% if item.title == page.title %}\n    {% unless forloop.first %}\n      {% assign prevIndex = forloop.index| minus: 2 %}\n      {% assign prev = sidebarItems[prevIndex] %}\n    {% endunless %}\n    {% unless forloop.last %}\n      {% assign nextIndex = forloop.index %}\n      {% assign next = sidebarItems[nextIndex] %}\n    {% endunless %}\n  {% endif %}\n{% endfor %}\n\n<div class=\"d-md-flex flex-1\">\n  {% include sidebar.html %}\n\n  <section class=\"col-lg-9 px-5 f4\">\n    <div class=\"container-md markdown-body mb-5\">\n      {% if page.version == 2 %}\n      <div class=\"flash flash-warn\">\n        You are reading the documentation for the <strong>Alpha</strong> version of Catalyst. The API and documentation is subject to change.\n        The documentation for the stable version can <a href=\"{{ site.baseurl }}/guide/introduction\">be found here</a>.\n      </div>\n      {% endif %}\n\n      <h1 class=\"mb-4 f0-light\">{{ page.title }}</h1>\n      {{ content }}\n      <div class=\"mt-4\">\n        <nav class=\"prev-next-links\" aria-label=\"Pagination\">\n          {% if prev %}\n          <a class=\"prev-next-links__button\" rel=\"previous\" href=\"{{ site.baseurl }}{{prev.url}}\" aria-label=\"Previous Page\">\n            <div class=\"f6 text-uppercase\">Previous</div>\n            {{prev.title}}\n          </a>\n          {% endif %} {% if next %}\n          <a class=\"prev-next-links__button\" rel=\"next\" href=\"{{ site.baseurl }}{{next.url}}\" aria-label=\"Next Page\">\n            <div class=\"f6 text-uppercase\">Next</div>\n            {{next.title}}\n          </a>\n          {% endif %}\n        </nav>\n      </div>\n    </div>\n  </section>\n</div>\n"
  },
  {
    "path": "docs/custom.css",
    "content": "pre {\n  font-size: 100% !important;\n}\ncode {\n  font-size: 90% !important;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5 {\n  margin: 1rem 0;\n  width: 100%;\n}\nul li {\n  margin-left: 1rem;\n}\n\n.top-100px {\n  top: 100px;\n}\n\n/* No preference or prefers light */\n:root:not([data-prefers-color-scheme='dark']),\nhtml[data-prefers-color-scheme='light'] {\n  --color-bg-canvas: rgb(255, 255, 255);\n  --color-bg-canvas-shadow: rgba(255, 255, 255, 0);\n  --color-bg-canvas-tertiary: #f6f8fa;\n  --color-text-primary: #24292e;\n  --color-markdown-code-bg: rgba(27, 31, 35, 0.05);\n  --color-accent-fg: #0969da;\n}\n/* Prefers dark */\nhtml[data-prefers-color-scheme='dark'] {\n  --color-bg-canvas: rgb(13, 17, 23);\n  --color-bg-canvas-shadow: rgba(13, 17, 23, 0);\n  --color-bg-canvas-tertiary: #161b22;\n  --color-text-primary: #c9d1d9;\n  --color-markdown-code-bg: rgba(240, 246, 252, 0.05);\n  --color-accent-fg: #58a6ff;\n}\n@media (prefers-color-scheme: dark) {\n  :root:not([data-prefers-color-scheme='light']) {\n    --color-bg-canvas: rgb(13, 17, 23);\n    --color-bg-canvas-shadow: rgba(13, 17, 23, 0);\n    --color-bg-canvas-tertiary: #161b22;\n    --color-text-primary: #c9d1d9;\n    --color-markdown-code-bg: rgba(240, 246, 252, 0.05);\n    --color-accent-fg: #58a6ff;\n  }\n}\n\nbody {\n  background-color: var(--color-bg-canvas);\n  color: var(--color-text-primary);\n}\n\na {\n  color: var(--color-accent-fg);\n}\n\n.min-height-full {\n  min-height: 100vh\n}\n\n.main-header {\n  height: 5rem;\n  z-index: 1;\n  background-image: linear-gradient(to top, var(--color-bg-canvas-shadow), var(--color-bg-canvas) 25%);\n}\n\n:root {\n  --logo-width: 18rem;\n}\n\n.logo {\n  min-width: var(--logo-width);\n}\n\n.sidebar {\n  height: calc(100vh - 5rem);\n  top: 5rem;\n  min-width: var(--logo-width);\n}\n\n@media only screen and (max-width : 768px) {\n  .main-header {\n    height: auto;\n    background: none;\n  }\n\n  .sidebar {\n    height: auto;\n  }\n\n  .logo.bg-gray {\n    background-color: inherit !important;\n    min-width: 9rem;\n  }\n}\n\n\n/* Sidebar */\n/* NB: `!important` is already used; so it’s required here */\n.bg-gray {\n  background-color: var(--color-bg-canvas-tertiary) !important;\n}\n\n/* Code Blocks & Syntax */\n.markdown-body .highlight pre,\n.markdown-body pre {\n  background-color: var(--color-bg-canvas-tertiary);\n  overflow: auto;\n}\n\n/* Inline Code */\n.markdown-body code,\n.markdown-body tt {\n  background-color: var(--color-markdown-code-bg);\n}\n\n/* Tables */\n.markdown-body table tr:nth-of-type(odd) th,\n.markdown-body table tr:nth-of-type(odd) td {\n  background-color: var(--color-bg-canvas);\n}\n.markdown-body table tr:nth-of-type(even) th,\n.markdown-body table tr:nth-of-type(even) td {\n  background-color: var(--color-bg-canvas-tertiary);\n}\n\n/* Override Primer .tooltipped default aria-label */\n.code-tooltip:after {\n  content: attr(data-title);\n  text-align: left;\n  font-size: 100%;\n}\n/* :after text will be announced by AT, this adds a separation between textContent and :after text */\n.code-tooltip:before {\n  content: ': ';\n  font-size: 0;\n}\n.code-tooltip {\n  scroll-margin-top: 150px;\n}\n\n\n/* Prev and next links */\n.prev-next-links {\n  display: flex;\n  gap: 16px;\n}\n\n.prev-next-links__button {\n  border: solid 1px;\n  padding: 16px;\n  border-radius: 4px;\n  flex: 1;\n}\n"
  },
  {
    "path": "docs/github-syntax.css",
    "content": "/* Shared */\n:root {\n\t--color-syntax-markup-deleted-text: #b31d28;\n\t--color-syntax-markup-deleted-bg: #ffeef0;\n\t--color-syntax-markup-inserted-text: #22863a;\n\t--color-syntax-markup-inserted-bg: #f0fff4;\n}\n\n/* No preference or prefers light */\n:root:not([data-prefers-color-scheme=dark]),\nhtml[data-prefers-color-scheme=light] {\n\t--color-syntax-text-primary: #24292e;\n\t--color-syntax-highlight: #ffffcc;\n\t--color-syntax-comment: #6a737d;\n\t--color-syntax-brackethighlighter-unmatched: #b31d28;\n\t--color-syntax-keyword: #24292e; /* upstream: #d73a49 */\n\t--color-syntax-string: #032f62;\n\t--color-syntax-constant: #005cc5;\n\t--color-syntax-entity-tag: #22863a;\n\t--color-syntax-entity: #6f42c1;\n}\n/* Prefers dark */\nhtml[data-prefers-color-scheme=dark] {\n\t--color-syntax-text-primary: #c9d1d9;\n\t--color-syntax-highlight: #ffffcc;\n\t--color-syntax-comment: #959da5;\n\t--color-syntax-brackethighlighter-unmatched: #d73a49;\n\t--color-syntax-keyword: #c9d1d9; /* upstream: #ea4a5a */\n\t--color-syntax-string: #79b8ff;\n\t--color-syntax-constant: #c8e1ff;\n\t--color-syntax-entity-tag: #7bcc72;\n\t--color-syntax-entity: #b392f0;\n}\n@media (prefers-color-scheme: dark) {\n  :root:not([data-prefers-color-scheme=light]) {\n\t  --color-syntax-text-primary: #c9d1d9;\n\t  --color-syntax-highlight: #ffffcc;\n\t  --color-syntax-comment: #959da5;\n\t  --color-syntax-brackethighlighter-unmatched: #d73a49;\n\t  --color-syntax-keyword: #c9d1d9; /* upstream: #ea4a5a */\n\t  --color-syntax-string: #79b8ff;\n\t  --color-syntax-constant: #c8e1ff;\n\t  --color-syntax-entity-tag: #7bcc72;\n\t  --color-syntax-entity: #b392f0;\n  }\n}\n\n.highlight .hll { background-color: var(--color-syntax-highlight) }\n\n.highlight .nx,\n.highlight .p { color: var(--color-syntax-primary); }\n\n/* Comment, Comment.Multiline, Comment.Single */\n.highlight .c,\n.highlight .cm,\n.highlight .c1 { color: var(--color-syntax-comment); font-style: italic }\n\n/* Comment.Preproc, Comment.Special */\n.highlight .cp,\n.highlight .cs { color: var(--color-syntax-comment); font-weight: bold; font-style: italic }\n\n/* Error */\n.highlight .err { color: var(--color-syntax-brackethighlighter-unmatched) }\n\n/* Generic.Error, Generic.Traceback */\n.highlight .gr, \n.highlight .gt { color: var(--color-syntax-brackethighlighter-unmatched) }\n\n/* Keyword, Keyword.Constant, Keyword.Declaration, Keyword.Namespace, Keyword.Pseudo, Keyword.Reserved, Keyword.Type */\n.highlight .k,\n.highlight .kc,\n.highlight .kd,\n.highlight .kn,\n.highlight .kp,\n.highlight .kr,\n.highlight .kt { color: var(--color-syntax-keyword); font-weight: bold }\n\n/* Literal.Number, Literal.String, Literal.Number.Float, Literal.Number.Hex, Literal.Number.Integer, Literal.Number.Oct, Literal.String.Backtick, Literal.String.Char, Literal.String.Doc, Literal.String.Double, Literal.String.Escape, Literal.String.Heredoc, Literal.String.Interpol, Literal.String.Other, Literal.String.Regex, Literal.String.Single, Literal.String.Symbol, Literal.Number.Integer.Long */\n.highlight .m,\n.highlight .s,\n.highlight .mf,\n.highlight .mh,\n.highlight .mi,\n.highlight .mo,\n.highlight .sb,\n.highlight .sc,\n.highlight .sd,\n.highlight .s2,\n.highlight .se,\n.highlight .sh,\n.highlight .si,\n.highlight .sx,\n.highlight .sr,\n.highlight .s1,\n.highlight .ss,\n.highlight .dl,\n.highlight .il { color: var(--color-syntax-string) }\n\n/* Name.Attribute, Name.Constant, Name.Variable, Name.Variable.Class, Name.Variable.Global, Name.Variable.Instance */\n.highlight .na,\n.highlight .no,\n.highlight .nv,\n.highlight .vc,\n.highlight .vg,\n.highlight .vi { color: var(--color-syntax-constant) }\n\n/* Name.Decorator, Name.Builtin, Name.Namespace, Name.Builtin.Pseudo */\n.highlight .nd,\n.highlight .nb,\n.highlight .nn,\n.highlight .bp { color: var(--color-syntax-constant); font-weight: bold; }\n\n/* Name.Tag */\n.highlight .nt { color: var(--color-syntax-entity-tag) }\n\n/* Name.Entity */\n.highlight .ni { color: var(--color-syntax-entity) }\n\n/* Name.Class, Name.Exception, Name.Function, Name.Label */\n.highlight .nc,\n.highlight .ne,\n.highlight .nf,\n.highlight .nl { color: var(--color-syntax-entity); font-weight: bold }\n\n/* Generic.Strong */\n.highlight .gs { font-weight: bold }\n\n/* Generic.Deleted */\n.highlight .gd { color: var(--color-syntax-markup-deleted-text); background-color: var(--color-syntax-markup-deleted-bg) }\n\n/* Generic.Inserted */ \n.highlight .gi { color: var(--color-syntax-markup-inserted-text); background-color: var(--color-syntax-markup-inserted-bg) }\n\n/* Operator, Operator.Word */\n.highlight .o,\n.highlight .ow { color: var(--color-syntax-text-primary); font-weight: bold }\n\n/* Text.Whitespace */\n.highlight .w { color: var(--color-syntax-text-primary) }\n\n/* Generic.Heading, Generic.Output, Generic.Prompt, Generic.Subheading */\n.highlight .gh,\n.highlight .go,\n.highlight .gp,\n.highlight .gu { color: var(--color-syntax-text-primary) }\n\n/* Generic.Emph */\n.highlight .ge { color: var(--color-syntax-text-primary); font-style: italic }\n"
  },
  {
    "path": "docs/index.html",
    "content": "---\nlayout: default\n---\n<section class=\"d-lg-flex p-3 flex-justify-center container-xl clearfix\">\n  <div class=\"mt-lg-6\">\n    <h1 class=\"h0-mktg mt-lg-6 mr-6\">Web Components<br class=\"hide-sm\"> made easy</h1>\n    <ul class=\"d-flex flex-justify-center list-style-none mt-4\">\n      <li class=\"ml-0 mt-3\">\n        <a href=\"{{ site.baseurl }}/guide/introduction\" class=\"f3 btn btn-large btn-outline bg-blue text-white\" style=\"height: 56px; line-height: 1.2;\">\n          Read the Guide\n        </a>\n      </li>\n    </ul>\n  </div>\n  <svg width=\"500px\" class=\"width-full\" xmlns=\"http://www.w3.org/2000/svg\" width=\"888\" height=\"475.27072\" viewBox=\"0 0 888 475.27072\"><title>true_love</title><rect x=\"402.54442\" y=\"219.17275\" width=\"2.57298\" height=\"13.89411\" transform=\"translate(-11.71503 -369.44906) rotate(26.64397)\" fill=\"#fff\"/><path d=\"M426.98456,248.842a66.00006,66.00006,0,0,0-93.33814,0l-.01788.01788a65.982,65.982,0,0,0-93.30231,93.30237l-.01788.01788,93.33807,93.33807,93.33814-93.33807A66,66,0,0,0,426.98456,248.842Z\" transform=\"translate(-156 -212.36464)\" fill=\"#ff6584\"/><path d=\"M709.42956,621.81706h-489.679a9.98831,9.98831,0,0,1-1.82989-.145l231.59565-401.157a16.2157,16.2157,0,0,1,28.22705,0L633.17308,489.72253l7.44637,12.8816Z\" transform=\"translate(-156 -212.36464)\" fill=\"#6c63ff\"/><polygon points=\"553.43 409.452 386.241 409.452 468.314 290.239 474.22 281.652 477.173 277.358 484.619 290.239 553.43 409.452\" opacity=\"0.2\"/><path d=\"M982.07935,621.36464H558.54722l82.07223-119.21293,5.9062-8.58777L753.47313,338.20663c7.01145-10.182,23.87881-10.81607,32.12223-1.92044a19.328,19.328,0,0,1,1.54006,1.92044Z\" transform=\"translate(-156 -212.36464)\" fill=\"#3f3d56\"/><rect y=\"407.93322\" width=\"888\" height=\"2.24072\" fill=\"#3f3d56\"/><ellipse cx=\"570.05705\" cy=\"586.26729\" rx=\"32.34192\" ry=\"10.15313\" transform=\"translate(-329.28848 33.15083) rotate(-21.1763)\" fill=\"#2f2e41\"/><circle cx=\"349.2698\" cy=\"382.74826\" r=\"64.68385\" fill=\"#2f2e41\"/><rect x=\"319.79361\" y=\"433.51279\" width=\"19.65079\" height=\"35.20766\" fill=\"#2f2e41\"/><rect x=\"359.09519\" y=\"433.51279\" width=\"19.65079\" height=\"35.20766\" fill=\"#2f2e41\"/><ellipse cx=\"336.16927\" cy=\"469.12985\" rx=\"16.37566\" ry=\"6.14087\" fill=\"#2f2e41\"/><ellipse cx=\"375.47085\" cy=\"468.31107\" rx=\"16.37566\" ry=\"6.14087\" fill=\"#2f2e41\"/><circle cx=\"350.90736\" cy=\"366.3726\" r=\"22.10714\" fill=\"#fff\"/><circle cx=\"350.90736\" cy=\"366.3726\" r=\"7.36905\" fill=\"#3f3d56\"/><path d=\"M442.52428,534.95878c-5.22292-23.39065,11.47266-47.02591,37.29064-52.79083s50.9816,8.52354,56.20452,31.91418-11.88759,32.01752-37.70556,37.78245S447.74721,558.34942,442.52428,534.95878Z\" transform=\"translate(-156 -212.36464)\" fill=\"#e6e6e6\"/><ellipse cx=\"440.41422\" cy=\"603.0993\" rx=\"32.34192\" ry=\"10.15313\" transform=\"translate(-453.46127 275.69894) rotate(-45)\" fill=\"#2f2e41\"/><path d=\"M473.49729,618.44821c0,6.33082,16.30083,18.832,34.38888,18.832s35.04764-17.82327,35.04764-24.15409-16.95958,1.22817-35.04764,1.22817S473.49729,612.11739,473.49729,618.44821Z\" transform=\"translate(-156 -212.36464)\" fill=\"#fff\"/><ellipse cx=\"623.94295\" cy=\"586.26729\" rx=\"10.15313\" ry=\"32.34192\" transform=\"translate(-304.12811 743.93025) rotate(-68.8237)\" fill=\"#2f2e41\"/><circle cx=\"532.7302\" cy=\"382.74826\" r=\"64.68385\" fill=\"#2f2e41\"/><rect x=\"698.5556\" y=\"645.87743\" width=\"19.65079\" height=\"35.20766\" transform=\"translate(1260.76198 1114.59789) rotate(-180)\" fill=\"#2f2e41\"/><rect x=\"659.25402\" y=\"645.87743\" width=\"19.65079\" height=\"35.20766\" transform=\"translate(1182.15883 1114.59789) rotate(-180)\" fill=\"#2f2e41\"/><ellipse cx=\"545.83073\" cy=\"469.12985\" rx=\"16.37566\" ry=\"6.14087\" fill=\"#2f2e41\"/><ellipse cx=\"506.52915\" cy=\"468.31107\" rx=\"16.37566\" ry=\"6.14087\" fill=\"#2f2e41\"/><circle cx=\"531.09264\" cy=\"366.3726\" r=\"22.10714\" fill=\"#fff\"/><circle cx=\"531.09264\" cy=\"366.3726\" r=\"7.36905\" fill=\"#3f3d56\"/><path d=\"M751.47572,534.95878c5.22292-23.39065-11.47266-47.02591-37.29064-52.79083s-50.9816,8.52354-56.20452,31.91418,11.88759,32.01752,37.70556,37.78245S746.25279,558.34942,751.47572,534.95878Z\" transform=\"translate(-156 -212.36464)\" fill=\"#6c63ff\"/><ellipse cx=\"753.58578\" cy=\"603.0993\" rx=\"10.15313\" ry=\"32.34192\" transform=\"translate(-361.73544 497.14467) rotate(-45)\" fill=\"#2f2e41\"/><path d=\"M720.50271,618.44821c0,6.33082-16.30083,18.832-34.38888,18.832s-35.04764-17.82327-35.04764-24.15409,16.95958,1.22817,35.04764,1.22817S720.50271,612.11739,720.50271,618.44821Z\" transform=\"translate(-156 -212.36464)\" fill=\"#fff\"/><path d=\"M1044,527.22724c0,41.80115-24.85012,56.39655-55.5043,56.39655s-55.5043-14.5954-55.5043-56.39655,55.5043-94.97881,55.5043-94.97881S1044,485.42608,1044,527.22724Z\" transform=\"translate(-156 -212.36464)\" fill=\"#e6e6e6\"/><polygon points=\"830.474 364.865 831.042 329.881 854.699 286.601 831.131 324.393 831.387 308.663 847.691 277.35 831.454 304.5 831.454 304.5 831.914 276.209 849.373 251.28 831.986 271.76 832.273 219.884 830.469 288.559 830.617 285.726 812.866 258.555 830.332 291.164 828.678 322.761 828.629 321.922 808.166 293.329 828.567 324.885 828.36 328.836 828.323 328.896 828.34 329.22 824.144 409.383 829.751 409.383 830.423 367.977 850.775 336.499 830.474 364.865\" fill=\"#3f3d56\"/></svg>\n</section>\n\n<section class=\"container-xl\">\n  <div class=\"mt-md-6\">\n    <h1 class=\"h000-mktg hide-sm mt-6 mr-6\">Catalyse your Web Components</h1>\n    <h1 class=\"h0-mktg hide-md hide-lg hide-xl mt-6 mr-6\">Catalyse your Web Components</h1>\n    <div class=\"d-md-flex f4\">\n      <div class=\"mt-4\">\n        {% highlight html %}\n<hello-world>\n  <input data-target=\"hello-world.name\" type=\"text\">\n\n  <button data-action=\"click:hello-world#greet\">\n    Greet\n  </button>\n\n  <span data-target=\"hello-world.output\">\n  </span>\n</hello-world>\n        {% endhighlight %}\n      </div>\n      <div class=\"\">\n        {% highlight js %}\nimport { controller, target } from \"@github/catalyst\"\n\n@controller\nclass HelloWorldElement extends HTMLElement {\n  @target name: HTMLElement\n  @target output: HTMLElement\n\n  greet() {\n    this.output.textContent = `Hello, ${this.name.value}!`\n  }\n}\n        {% endhighlight %}\n      </div>\n    </div>\n  </div>\n</section>\n"
  },
  {
    "path": "docs/index.js",
    "content": "function storeColorSchemePreference() {\n  // Get color scheme preference from URL\n  const url = new URL(window.location.href, window.location.origin)\n  const params = new URLSearchParams(url.search)\n\n  // Return early if there’s nothing to store\n  if (!params.has('prefers-color-scheme')) {\n    return\n  }\n\n  const param = params.get('prefers-color-scheme').toLowerCase()\n  if (['light', 'dark'].includes(param)) {\n    // Store preference in Local Storage\n    window.localStorage.setItem('prefers-color-scheme', param)\n  } else {\n    // Clear preference in Local Storage\n    window.localStorage.clear('prefers-color-scheme')\n  }\n\n  // Remove color scheme preference from URL\n  params.delete('prefers-color-scheme')\n  url.search = params.toString()\n  history.replaceState(null, '', url)\n}\n\nfunction applyColorSchemePreference() {\n  // Get color scheme preference from Local Storage\n  const preference = window.localStorage.getItem('prefers-color-scheme')\n\n  // Return early if no preference exists\n  if (!preference) {\n    return\n  }\n\n  // Write preference to <body> attribute\n  document.body.parentElement.setAttribute('data-prefers-color-scheme', preference)\n}\n\nstoreColorSchemePreference()\napplyColorSchemePreference()\n\nfunction addAnnotations() {\n  for (const codeBlock of document.querySelectorAll('.highlighter-rouge')) {\n    const comment = parseCommentNode(codeBlock)\n    if (comment.annotations) annotate(codeBlock, comment.annotations)\n  }\n}\n\nfunction parseCommentNode(el) {\n  const stopAtEl = el.previousElementSibling\n  let t = el.previousSibling\n  if (!stopAtEl && !t) return\n  let comment\n  while (t && t !== stopAtEl) {\n    if (t.nodeType === 8) {\n      comment = t\n      break\n    } else {\n      t = t.previousSibling\n    }\n  }\n\n  if (!comment) return {}\n\n  const [type, ...details] = comment.textContent.trim().split('\\n')\n\n  return {\n    noDemo: type.match(/no_demo/),\n    onlyDemo: type.match(/only_demo/),\n    annotations: type.match(/annotations/) && details\n  }\n}\n\nlet matchIndex = 0\nfunction annotate(codeBlock, items) {\n  const noMatch = new Set(items)\n  const annotated = new WeakMap()\n  for (const el of codeBlock.querySelectorAll('code > span')) {\n    for (const item of items) {\n      let currentNode = el\n      const [pattern, rest] = item.split(/: /)\n      const [title, link] = (rest || '').split(/ \\| /)\n      const parts = pattern.split(' ')\n      let toAnnotate = []\n      for (const part of parts) {\n        if (currentNode && currentNode.textContent.match(part)) {\n          toAnnotate.push(currentNode)\n          currentNode = currentNode.nextElementSibling\n        } else {\n          toAnnotate = []\n          break\n        }\n      }\n      for (const node of toAnnotate) {\n        noMatch.delete(item)\n        if (title) {\n          if (annotated.get(node)) {\n            continue\n          }\n          annotated.set(node, title)\n          const a = document.createElement('a')\n          a.className = `${node.className} code-tooltip tooltipped tooltipped-multiline tooltipped-se bg-gray text-underline`\n          a.id = `match-${matchIndex++}`\n          a.href = link || `#${a.id}`\n          a.setAttribute('data-title', title)\n          a.textContent = node.textContent\n          node.replaceWith(a)\n        } else {\n          node.classList.add('bg-gray')\n        }\n      }\n    }\n  }\n  for (const pattern of noMatch) {\n    // eslint-disable-next-line no-console\n    console.error(`Code annotations: No match found for \"${pattern}\"`)\n  }\n}\n\naddAnnotations()\n"
  },
  {
    "path": "docs/primer.css",
    "content": "/*!\n * Primer\n * http://primer.github.io\n *\n * Released under MIT license. Copyright (c) 2019 GitHub Inc.\n *//*!\n * @primer/css/core\n * http://primer.style/css\n *\n * Released under MIT license. Copyright (c) 2019 GitHub Inc.\n */.octicon{display:inline-block;vertical-align:text-top;fill:currentColor}/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}template,[hidden]{display:none !important}a{background-color:transparent}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background-color:#ff0;color:#1b1f23}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:600}button,input{overflow:visible}button,select{text-transform:none}button,html [type=\"button\"],[type=\"reset\"],[type=\"submit\"]{-webkit-appearance:button}button::-moz-focus-inner,[type=\"button\"]::-moz-focus-inner,[type=\"reset\"]::-moz-focus-inner,[type=\"submit\"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=\"button\"]:-moz-focusring,[type=\"reset\"]:-moz-focusring,[type=\"submit\"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:0.35em 0.625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type=\"checkbox\"],[type=\"radio\"]{box-sizing:border-box;padding:0}[type=\"number\"]::-webkit-inner-spin-button,[type=\"number\"]::-webkit-outer-spin-button{height:auto}[type=\"search\"]{-webkit-appearance:textfield;outline-offset:-2px}[type=\"search\"]::-webkit-search-cancel-button,[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:0.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}*{box-sizing:border-box}input,select,textarea,button{font-family:inherit;font-size:inherit;line-height:inherit}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\";font-size:14px;line-height:1.5;color:#24292e;background-color:#fff}a{color:#0366d6;text-decoration:none}a:hover{text-decoration:underline}b,strong{font-weight:600}hr,.rule{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #dfe2e5}hr::before,.rule::before{display:table;content:\"\"}hr::after,.rule::after{display:table;clear:both;content:\"\"}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}button{cursor:pointer;border-radius:0}[hidden][hidden]{display:none !important}details summary{cursor:pointer}details:not([open])>*:not(summary){display:none !important}kbd{display:inline-block;padding:3px 5px;font:11px \"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #d1d5da;border-bottom-color:#d1d5da;border-radius:3px;box-shadow:inset 0 -1px 0 #d1d5da}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:0}h1{font-size:32px;font-weight:600}h2{font-size:24px;font-weight:600}h3{font-size:20px;font-weight:600}h4{font-size:16px;font-weight:600}h5{font-size:14px;font-weight:600}h6{font-size:12px;font-weight:600}p{margin-top:0;margin-bottom:10px}small{font-size:90%}blockquote{margin:0}ul,ol{padding-left:0;margin-top:0;margin-bottom:0}ol ol,ul ol{list-style-type:lower-roman}ul ul ol,ul ol ol,ol ul ol,ol ol ol{list-style-type:lower-alpha}dd{margin-left:0}tt,code{font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;font-size:12px}pre{margin-top:0;margin-bottom:0;font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;font-size:12px}.octicon{vertical-align:text-bottom}.Box{background-color:#fff;border:1px solid #d1d5da;border-radius:3px}.Box--condensed{line-height:1.25}.Box--condensed .Box-header{padding:8px 16px}.Box--condensed .Box-body{padding:8px 16px}.Box--condensed .Box-footer{padding:8px 16px}.Box--condensed .Box-btn-octicon.btn-octicon{padding:8px 16px;margin:-8px -16px;line-height:1.25}.Box--condensed .Box-row{padding:8px 16px}.Box--spacious .Box-header{padding:24px;line-height:1.25}.Box--spacious .Box-title{font-size:20px}.Box--spacious .Box-body{padding:24px}.Box--spacious .Box-footer{padding:24px}.Box--spacious .Box-btn-octicon.btn-octicon{padding:24px;margin:-24px -24px}.Box--spacious .Box-row{padding:24px}.Box-header{padding:16px;margin:-1px -1px 0;background-color:#f6f8fa;border-color:#d1d5da;border-style:solid;border-width:1px;border-top-left-radius:3px;border-top-right-radius:3px}.Box-title{font-size:14px;font-weight:600}.Box-body{padding:16px;border-bottom:1px solid #e1e4e8}.Box-body:last-of-type{margin-bottom:-1px;border-bottom-right-radius:2px;border-bottom-left-radius:2px}.Box-row{padding:16px;margin-top:-1px;list-style-type:none;border-top:1px solid #e1e4e8}.Box-row:first-of-type{border-top-color:transparent;border-top-left-radius:2px;border-top-right-radius:2px}.Box-row:last-of-type{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.Box-row.Box-row--unread,.Box-row.unread{box-shadow:2px 0 0 #0366d6 inset}.Box-row.navigation-focus .Box-row--drag-button{color:#0366d6;cursor:grab;opacity:100}.Box-row.navigation-focus.is-dragging .Box-row--drag-button{cursor:grabbing}.Box-row.navigation-focus.sortable-chosen{background-color:#fafbfc}.Box-row.navigation-focus.sortable-ghost{background-color:#f6f8fa}.Box-row.navigation-focus.sortable-ghost .Box-row--drag-hide{opacity:0}.Box-row--focus-gray.navigation-focus{background-color:#f6f8fa}.Box-row--focus-blue.navigation-focus{background-color:#f1f8ff}.Box-row--hover-gray:hover{background-color:#f6f8fa}.Box-row--hover-blue:hover{background-color:#f1f8ff}@media (min-width: 768px){.Box-row-link{color:#24292e;text-decoration:none}.Box-row-link:hover{color:#0366d6;text-decoration:none}}.Box-row--drag-button{opacity:0}.Box-footer{padding:16px;margin-top:-1px;border-top:1px solid #e1e4e8}.Box--scrollable{max-height:324px;overflow:scroll}.Box--blue{border-color:#c8e1ff}.Box--blue .Box-header{background-color:#f1f8ff;border-color:#c8e1ff}.Box--blue .Box-body{border-color:#c8e1ff}.Box--blue .Box-row{border-color:#c8e1ff}.Box--blue .Box-footer{border-color:#c8e1ff}.Box--danger{border-color:#d73a49}.Box--danger .Box-row:first-of-type{border-color:#d73a49}.Box--danger .Box-body:last-of-type{border-color:#d73a49}.Box-header--blue{background-color:#f1f8ff;border-color:#c8e1ff}.Box-row--yellow{background-color:#fffbdd}.Box-row--blue{background-color:#f1f8ff}.Box-row--gray{background-color:#f6f8fa}.Box-btn-octicon.btn-octicon{padding:16px 16px;margin:-16px -16px;line-height:1.5}.breadcrumb-item{display:inline-block;margin-left:-0.35em;white-space:nowrap;list-style:none}.breadcrumb-item::after{padding-right:.5em;padding-left:.5em;color:#e1e4e8;content:\"/\"}.breadcrumb-item:first-child{margin-left:0}.breadcrumb-item-selected,.breadcrumb-item[aria-current]{color:#586069}.breadcrumb-item-selected::after,.breadcrumb-item[aria-current]::after{content:none}.btn{position:relative;display:inline-block;padding:6px 12px;font-size:14px;font-weight:600;line-height:20px;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-repeat:repeat-x;background-position:-1px -1px;background-size:110% 110%;border:1px solid rgba(27,31,35,0.2);border-radius:0.25em;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn i{font-style:normal;font-weight:500;opacity:0.75}.btn .octicon{vertical-align:text-top}.btn .Counter{color:#586069;text-shadow:none;background-color:rgba(27,31,35,0.1)}.btn:hover{text-decoration:none;background-repeat:repeat-x}.btn:focus{outline:0}.btn:disabled,.btn.disabled,.btn[aria-disabled=true]{cursor:default;background-position:0 0}.btn:active,.btn.selected,.btn[aria-selected=true]{background-image:none}.btn{color:#24292e;background-color:#eff3f6;background-image:linear-gradient(-180deg, #fafbfc 0%, #eff3f6 90%)}.btn:focus,.btn.focus{box-shadow:0 0 0 0.2em rgba(3,102,214,0.3)}.btn:hover,.btn.hover{background-color:#e6ebf1;background-image:linear-gradient(-180deg, #f0f3f6 0%, #e6ebf1 90%);background-position:-.5em;border-color:rgba(27,31,35,0.35)}.btn:active,.btn.selected,.btn[aria-selected=true],[open]>.btn{background-color:#e9ecef;background-image:none;border-color:rgba(27,31,35,0.35);box-shadow:inset 0 0.15em 0.3em rgba(27,31,35,0.15)}.btn:disabled,.btn.disabled,.btn[aria-disabled=true]{color:rgba(36,41,46,0.4);background-color:#eff3f6;background-image:none;border-color:rgba(27,31,35,0.2);box-shadow:none}.btn-primary{color:#fff;background-color:#28a745;background-image:linear-gradient(-180deg, #34d058 0%, #28a745 90%)}.btn-primary:focus,.btn-primary.focus{box-shadow:0 0 0 0.2em rgba(52,208,88,0.4)}.btn-primary:hover,.btn-primary.hover{background-color:#269f42;background-image:linear-gradient(-180deg, #2fcb53 0%, #269f42 90%);background-position:-.5em;border-color:rgba(27,31,35,0.5)}.btn-primary:active,.btn-primary.selected,.btn-primary[aria-selected=true],[open]>.btn-primary{background-color:#279f43;background-image:none;border-color:rgba(27,31,35,0.5);box-shadow:inset 0 0.15em 0.3em rgba(27,31,35,0.15)}.btn-primary:disabled,.btn-primary.disabled,.btn-primary[aria-disabled=true]{color:rgba(255,255,255,0.75);background-color:#94d3a2;background-image:none;border-color:rgba(27,31,35,0.2);box-shadow:none}.btn-primary .Counter{color:#29b249;background-color:#fff}.btn-blue{color:#fff;background-color:#0361cc;background-image:linear-gradient(-180deg, #0679fc 0%, #0361cc 90%)}.btn-blue:focus,.btn-blue.focus{box-shadow:0 0 0 0.2em rgba(6,121,252,0.4)}.btn-blue:hover,.btn-blue.hover{background-color:#035cc2;background-image:linear-gradient(-180deg, #0374f4 0%, #035cc2 90%);background-position:-.5em;border-color:rgba(27,31,35,0.5)}.btn-blue:active,.btn-blue.selected,.btn-blue[aria-selected=true],[open]>.btn-blue{background-color:#045cc1;background-image:none;border-color:rgba(27,31,35,0.5);box-shadow:inset 0 0.15em 0.3em rgba(27,31,35,0.15)}.btn-blue:disabled,.btn-blue.disabled,.btn-blue[aria-disabled=true]{color:rgba(255,255,255,0.75);background-color:#81b0e5;background-image:none;border-color:rgba(27,31,35,0.2);box-shadow:none}.btn-blue .Counter{color:#0366d6;background-color:#fff}.btn-danger{color:#cb2431;background-color:#fafbfc;background-image:linear-gradient(-180deg, #fafbfc 0%, #eff3f6 90%)}.btn-danger:focus{box-shadow:0 0 0 0.2em rgba(203,36,49,0.4)}.btn-danger:hover{color:#fff;background-color:#cb2431;background-image:linear-gradient(-180deg, #de4450 0%, #cb2431 90%);border-color:rgba(27,31,35,0.5)}.btn-danger:hover .Counter{color:#fff}.btn-danger:active,.btn-danger.selected,.btn-danger[aria-selected=true],[open]>.btn-danger{color:#fff;background-color:#b5202c;background-image:none;border-color:rgba(27,31,35,0.5);box-shadow:inset 0 0.15em 0.3em rgba(27,31,35,0.15)}.btn-danger:disabled,.btn-danger.disabled,.btn-danger[aria-disabled=true]{color:rgba(203,36,49,0.4);background-color:#eff3f6;background-image:none;border-color:rgba(27,31,35,0.2);box-shadow:none}.btn-outline{color:#0366d6;background-color:#fff;background-image:none}.btn-outline .Counter{background-color:rgba(27,31,35,0.07)}.btn-outline:hover,.btn-outline:active,.btn-outline.selected,.btn-outline[aria-selected=true],[open]>.btn-outline{color:#fff;background-color:#0366d6;background-image:none;border-color:#0366d6}.btn-outline:hover .Counter,.btn-outline:active .Counter,.btn-outline.selected .Counter,.btn-outline[aria-selected=true] .Counter,[open]>.btn-outline .Counter{color:#0366d6;background-color:#fff}.btn-outline:focus{border-color:#0366d6;box-shadow:0 0 0 0.2em rgba(3,102,214,0.4)}.btn-outline:disabled,.btn-outline.disabled,.btn-outline[aria-disabled=true]{color:rgba(27,31,35,0.3);background-color:#fff;border-color:rgba(27,31,35,0.15);box-shadow:none}.btn-with-count{float:left;border-top-right-radius:0;border-bottom-right-radius:0}.btn-sm{padding:3px 10px;font-size:12px;line-height:20px}.btn-large{padding:.75em 1.25em;font-size:inherit;border-radius:6px}.btn-block{display:block;width:100%;text-align:center}.btn-link{display:inline-block;padding:0;font-size:inherit;color:#0366d6;text-decoration:none;white-space:nowrap;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-link:hover{text-decoration:underline}.btn-link:disabled,.btn-link:disabled:hover,.btn-link[aria-disabled=true],.btn-link[aria-disabled=true]:hover{color:rgba(88,96,105,0.5);cursor:default}.btn-invisible{color:#0366d6;background-color:#fff;background-image:none;border:0}.btn-invisible:hover,.btn-invisible:active,.btn-invisible:focus,.btn-invisible.selected,.btn-invisible[aria-selected=true],.btn-invisible.zeroclipboard-is-hover,.btn-invisible.zeroclipboard-is-active{color:#0366d6;background:none;outline:none;box-shadow:none}.btn-octicon{display:inline-block;padding:5px;margin-left:5px;line-height:1;color:#586069;vertical-align:middle;background:transparent;border:0}.btn-octicon:hover{color:#0366d6}.btn-octicon.disabled,.btn-octicon[aria-disabled=true]{color:#959da5;cursor:default}.btn-octicon.disabled:hover,.btn-octicon[aria-disabled=true]:hover{color:#959da5}.btn-octicon-danger:hover{color:#cb2431}.BtnGroup{display:inline-block;vertical-align:middle}.BtnGroup::before{display:table;content:\"\"}.BtnGroup::after{display:table;clear:both;content:\"\"}.BtnGroup+.BtnGroup,.BtnGroup+.btn{margin-left:4px}.BtnGroup-item{position:relative;float:left;border-right-width:0;border-radius:0}.BtnGroup-item:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.BtnGroup-item:last-child{border-right-width:1px;border-top-right-radius:3px;border-bottom-right-radius:3px}.BtnGroup-item.selected,.BtnGroup-item[aria-selected=true],.BtnGroup-item:focus,.BtnGroup-item:active,.BtnGroup-item:hover{border-right-width:1px}.BtnGroup-item.selected+.BtnGroup-item,.BtnGroup-item.selected+.BtnGroup-parent .BtnGroup-item,.BtnGroup-item[aria-selected=true]+.BtnGroup-item,.BtnGroup-item[aria-selected=true]+.BtnGroup-parent .BtnGroup-item,.BtnGroup-item:focus+.BtnGroup-item,.BtnGroup-item:focus+.BtnGroup-parent .BtnGroup-item,.BtnGroup-item:active+.BtnGroup-item,.BtnGroup-item:active+.BtnGroup-parent .BtnGroup-item,.BtnGroup-item:hover+.BtnGroup-item,.BtnGroup-item:hover+.BtnGroup-parent .BtnGroup-item{border-left-width:0}.BtnGroup-parent{float:left}.BtnGroup-parent:first-child .BtnGroup-item{border-top-left-radius:3px;border-bottom-left-radius:3px}.BtnGroup-parent:last-child .BtnGroup-item{border-right-width:1px;border-top-right-radius:3px;border-bottom-right-radius:3px}.BtnGroup-parent .BtnGroup-item{border-right-width:0;border-radius:0}.BtnGroup-parent.selected .BtnGroup-item,.BtnGroup-parent[aria-selected=true] .BtnGroup-item,.BtnGroup-parent:focus .BtnGroup-item,.BtnGroup-parent:active .BtnGroup-item,.BtnGroup-parent:hover .BtnGroup-item{border-right-width:1px}.BtnGroup-parent.selected+.BtnGroup-item,.BtnGroup-parent.selected+.BtnGroup-parent .BtnGroup-item,.BtnGroup-parent[aria-selected=true]+.BtnGroup-item,.BtnGroup-parent[aria-selected=true]+.BtnGroup-parent .BtnGroup-item,.BtnGroup-parent:focus+.BtnGroup-item,.BtnGroup-parent:focus+.BtnGroup-parent .BtnGroup-item,.BtnGroup-parent:active+.BtnGroup-item,.BtnGroup-parent:active+.BtnGroup-parent .BtnGroup-item,.BtnGroup-parent:hover+.BtnGroup-item,.BtnGroup-parent:hover+.BtnGroup-parent .BtnGroup-item{border-left-width:0}.BtnGroup-item:focus,.BtnGroup-item:active,.BtnGroup-parent:focus,.BtnGroup-parent:active{z-index:1}.close-button{padding:0;background:transparent;border:0;outline:none}.hidden-text-expander{display:block}.hidden-text-expander.inline{position:relative;top:-1px;display:inline-block;margin-left:5px;line-height:0}.hidden-text-expander a,.ellipsis-expander{display:inline-block;height:12px;padding:0 5px 5px;font-size:12px;font-weight:600;line-height:6px;color:#444d56;text-decoration:none;vertical-align:middle;background:#dfe2e5;border:0;border-radius:1px}.hidden-text-expander a:hover,.ellipsis-expander:hover{text-decoration:none;background-color:#c6cbd1}.hidden-text-expander a:active,.ellipsis-expander:active{color:#fff;background-color:#2188ff}.social-count{float:left;padding:3px 10px;font-size:12px;font-weight:600;line-height:20px;color:#24292e;vertical-align:middle;background-color:#fff;border:1px solid rgba(27,31,35,0.2);border-left:0;border-top-right-radius:3px;border-bottom-right-radius:3px}.social-count:hover,.social-count:active{text-decoration:none}.social-count:hover{color:#0366d6;cursor:pointer}.TableObject{display:table}.TableObject-item{display:table-cell;width:1%;white-space:nowrap;vertical-align:middle}.TableObject-item--primary{width:99%}fieldset{padding:0;margin:0;border:0}label{font-weight:600}.form-control,.form-select{min-height:34px;padding:6px 8px;font-size:16px;line-height:20px;color:#24292e;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #d1d5da;border-radius:3px;outline:none;box-shadow:inset 0 1px 2px rgba(27,31,35,0.075)}.form-control.focus,.form-control:focus,.form-select.focus,.form-select:focus{border-color:#2188ff;outline:none;box-shadow:inset 0 1px 2px rgba(27,31,35,0.075),0 0 0 0.2em rgba(3,102,214,0.3)}@media (min-width: 768px){.form-control,.form-select{font-size:14px}}.input-contrast{background-color:#fafbfc}.input-contrast:focus{background-color:#fff}.input-dark{color:#fff;background-color:rgba(255,255,255,0.15);border-color:transparent}.input-dark:-ms-input-placeholder{color:inherit;opacity:0.6}.input-dark::-ms-input-placeholder{color:inherit;opacity:0.6}.input-dark::placeholder{color:inherit;opacity:0.6}.input-dark.focus,.input-dark:focus{border-color:rgba(27,31,35,0.3);box-shadow:0 0 0 0.2em rgba(121,184,255,0.4)}:-ms-input-placeholder{color:#6a737d}::-ms-input-placeholder{color:#6a737d}::placeholder{color:#6a737d}.input-sm{min-height:28px;padding-top:3px;padding-bottom:3px;font-size:12px;line-height:20px}.input-lg{padding:4px 10px;font-size:16px}.input-block{display:block;width:100%}.input-monospace{font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace}.input-hide-webkit-autofill::-webkit-contacts-auto-fill-button{position:absolute;right:0;display:none !important;pointer-events:none;visibility:hidden}.form-checkbox{padding-left:20px;margin:15px 0;vertical-align:middle}.form-checkbox label em.highlight{position:relative;left:-4px;padding:2px 4px;font-style:normal;background:#fffbdd;border-radius:3px}.form-checkbox input[type=checkbox],.form-checkbox input[type=radio]{float:left;margin:5px 0 0 -20px;vertical-align:middle}.form-checkbox .note{display:block;margin:0;font-size:12px;font-weight:400;color:#586069}.form-checkbox-details{display:none}.form-checkbox-details-trigger:checked ~ * .form-checkbox-details,.form-checkbox-details-trigger:checked ~ .form-checkbox-details{display:block}.hfields{margin:15px 0}.hfields::before{display:table;content:\"\"}.hfields::after{display:table;clear:both;content:\"\"}.hfields .form-group{float:left;margin:0 30px 0 0}.hfields .form-group dt label{display:inline-block;margin:5px 0 0;color:#586069}.hfields .form-group dt img{position:relative;top:-2px}.hfields .btn{float:left;margin:28px 25px 0 -20px}.hfields .form-select{margin-top:5px}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{margin:0;-webkit-appearance:none;appearance:none}.form-actions::before{display:table;content:\"\"}.form-actions::after{display:table;clear:both;content:\"\"}.form-actions .btn{float:right}.form-actions .btn+.btn{margin-right:5px}.form-warning{padding:8px 10px;margin:10px 0;font-size:14px;color:#735c0f;background:#fffbdd;border:1px solid #d9d0a5;border-radius:3px}.form-warning p{margin:0;line-height:1.5}.form-warning a{font-weight:600}.form-select{display:inline-block;max-width:100%;height:34px;padding-right:24px;background-color:#fff;background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAUCAMAAACzvE1FAAAADFBMVEUzMzMzMzMzMzMzMzMKAG/3AAAAA3RSTlMAf4C/aSLHAAAAPElEQVR42q3NMQ4AIAgEQTn//2cLdRKppSGzBYwzVXvznNWs8C58CiussPJj8h6NwgorrKRdTvuV9v16Afn0AYFOB7aYAAAAAElFTkSuQmCC\");background-repeat:no-repeat;background-position:right 8px center;background-size:8px 10px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.form-select::-ms-expand{opacity:0}.form-select[multiple]{height:auto}.select-sm{height:28px;min-height:28px;padding-top:3px;padding-bottom:3px;font-size:12px}.select-sm[multiple]{height:auto;min-height:0}.form-group{margin:15px 0}.form-group .form-control{width:440px;max-width:100%;margin-right:5px;background-color:#fafbfc}.form-group .form-control:focus{background-color:#fff}.form-group .form-control.shorter{width:130px}.form-group .form-control.short{width:250px}.form-group .form-control.long{width:100%}.form-group textarea.form-control{width:100%;height:200px;min-height:200px}.form-group textarea.form-control.short{height:50px;min-height:50px}.form-group dt{margin:0 0 6px}.form-group label{position:relative}.form-group.flattened dt{float:left;margin:0;line-height:32px}.form-group.flattened dd{line-height:32px}.form-group dd h4{margin:4px 0 0}.form-group dd h4.is-error{color:#cb2431}.form-group dd h4.is-success{color:#28a745}.form-group dd h4+.note{margin-top:0}.form-group.required dt label::after{padding-left:5px;color:#cb2431;content:\"*\"}.form-group .success,.form-group .error,.form-group .indicator{display:none;font-size:12px;font-weight:600}.form-group.loading{opacity:0.5}.form-group.loading .indicator{display:inline}.form-group.loading .spinner{display:inline-block;vertical-align:middle}.form-group.successful .success{display:inline;color:#28a745}.form-group.warn .warning,.form-group.warn .error,.form-group.errored .warning,.form-group.errored .error{position:absolute;z-index:10;display:block;max-width:450px;padding:5px 8px;margin:4px 0 0;font-size:13px;font-weight:400;border-style:solid;border-width:1px;border-radius:3px}.form-group.warn .warning::after,.form-group.warn .warning::before,.form-group.warn .error::after,.form-group.warn .error::before,.form-group.errored .warning::after,.form-group.errored .warning::before,.form-group.errored .error::after,.form-group.errored .error::before{position:absolute;bottom:100%;left:10px;z-index:15;width:0;height:0;pointer-events:none;content:\" \";border:solid transparent}.form-group.warn .warning::after,.form-group.warn .error::after,.form-group.errored .warning::after,.form-group.errored .error::after{border-width:5px}.form-group.warn .warning::before,.form-group.warn .error::before,.form-group.errored .warning::before,.form-group.errored .error::before{margin-left:-1px;border-width:6px}.form-group.warn .warning{color:#735c0f;background-color:#fffbdd;border-color:#d9d0a5}.form-group.warn .warning::after{border-bottom-color:#fffbdd}.form-group.warn .warning::before{border-bottom-color:#d9d0a5}.form-group.errored label{color:#cb2431}.form-group.errored .error{color:#86181d;background-color:#ffdce0;border-color:#cea0a5}.form-group.errored .error::after{border-bottom-color:#ffdce0}.form-group.errored .error::before{border-bottom-color:#cea0a5}.note{min-height:17px;margin:4px 0 2px;font-size:12px;color:#586069}.note .spinner{margin-right:3px;vertical-align:middle}dl.form-group>dd .form-control.is-autocheck-loading,dl.form-group>dd .form-control.is-autocheck-successful,dl.form-group>dd .form-control.is-autocheck-errored{padding-right:30px}dl.form-group>dd .form-control.is-autocheck-loading{background-image:url(\"/images/spinners/octocat-spinner-16px.gif\")}dl.form-group>dd .form-control.is-autocheck-successful{background-image:url(\"/images/modules/ajax/success.png\")}dl.form-group>dd .form-control.is-autocheck-errored{background-image:url(\"/images/modules/ajax/error.png\")}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-moz-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){dl.form-group>dd .form-control.is-autocheck-loading,dl.form-group>dd .form-control.is-autocheck-successful,dl.form-group>dd .form-control.is-autocheck-errored{background-size:16px 16px}dl.form-group>dd .form-control.is-autocheck-loading{background-image:url(\"/images/spinners/octocat-spinner-32.gif\")}dl.form-group>dd .form-control.is-autocheck-successful{background-image:url(\"/images/modules/ajax/success@2x.png\")}dl.form-group>dd .form-control.is-autocheck-errored{background-image:url(\"/images/modules/ajax/error@2x.png\")}}.status-indicator{display:inline-block;width:16px;height:16px;margin-left:5px}.status-indicator .octicon{display:none}.status-indicator-success::before{content:\"\"}.status-indicator-success .octicon-check{display:inline-block;color:#28a745;fill:#28a745}.status-indicator-success .octicon-x{display:none}.status-indicator-failed::before{content:\"\"}.status-indicator-failed .octicon-check{display:none}.status-indicator-failed .octicon-x{display:inline-block;color:#cb2431;fill:#d73a49}.status-indicator-loading{width:16px;background-image:url(\"/images/spinners/octocat-spinner-32-EAF2F5.gif\");background-repeat:no-repeat;background-position:0 0;background-size:16px}.inline-form{display:inline-block}.inline-form .btn-plain{background-color:transparent;border:0}.drag-and-drop{padding:7px 10px;margin:0;font-size:13px;line-height:16px;color:#586069;background-color:#fafbfc;border:1px solid #c3c8cf;border-top:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.drag-and-drop .default,.drag-and-drop .loading,.drag-and-drop .error{display:none}.drag-and-drop .error{color:#cb2431}.drag-and-drop img{vertical-align:top}.is-default .drag-and-drop .default{display:inline-block}.is-uploading .drag-and-drop .loading{display:inline-block}.is-bad-file .drag-and-drop .bad-file{display:inline-block}.is-duplicate-filename .drag-and-drop .duplicate-filename{display:inline-block}.is-too-big .drag-and-drop .too-big{display:inline-block}.is-hidden-file .drag-and-drop .hidden-file{display:inline-block}.is-empty .drag-and-drop .empty{display:inline-block}.is-bad-permissions .drag-and-drop .bad-permissions{display:inline-block}.is-repository-required .drag-and-drop .repository-required{display:inline-block}.drag-and-drop-error-info{font-weight:400;color:#586069}.drag-and-drop-error-info a{color:#0366d6}.is-failed .drag-and-drop .failed-request{display:inline-block}.manual-file-chooser{position:absolute;width:240px;padding:5px;margin-left:-80px;cursor:pointer;opacity:0.0001}.manual-file-chooser:hover+.manual-file-chooser-text{text-decoration:underline}.btn .manual-file-chooser{top:0;padding:0;line-height:34px}.upload-enabled textarea{display:block;border-bottom:1px dashed #dfe2e5;border-bottom-right-radius:0;border-bottom-left-radius:0}.upload-enabled.focused{border-radius:3px;box-shadow:inset 0 1px 2px rgba(27,31,35,0.075),0 0 0 0.2em rgba(3,102,214,0.3)}.upload-enabled.focused .form-control{box-shadow:none}.upload-enabled.focused .drag-and-drop{border-color:#4a9eff}.dragover textarea,.dragover .drag-and-drop{box-shadow:#c9ff00 0 0 3px}.write-content{position:relative}.previewable-comment-form{position:relative}.previewable-comment-form .tabnav{position:relative;padding:8px 8px 0}.previewable-comment-form .comment{border:1px solid #c3c8cf}.previewable-comment-form .comment-form-error{margin-bottom:8px}.previewable-comment-form .write-content,.previewable-comment-form .preview-content{display:none;margin:0 8px 8px}.previewable-comment-form.write-selected .write-content,.previewable-comment-form.preview-selected .preview-content{display:block}.previewable-comment-form textarea{display:block;width:100%;min-height:100px;max-height:500px;padding:8px;resize:vertical}.form-action-spacious{margin-top:10px}div.composer{margin-top:0;border:0}.composer .comment-form-textarea{height:200px;min-height:200px}.composer .tabnav{margin:0 0 10px}h2.account{margin:15px 0 0;font-size:18px;font-weight:400;color:#586069}p.explain{position:relative;font-size:12px;color:#586069}p.explain strong{color:#24292e}p.explain .octicon{margin-right:5px;color:#959da5}p.explain .minibutton{top:-4px;float:right}.form-group label{position:static}.input-group{display:table}.input-group .form-control{position:relative;width:100%}.input-group .form-control:focus{z-index:2}.input-group .form-control+.btn{margin-left:0}.input-group.inline{display:inline-table}.input-group .form-control,.input-group-button{display:table-cell}.input-group-button{width:1%;vertical-align:middle}.input-group .form-control:first-child,.input-group-button:first-child .btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-button:first-child .btn{margin-right:-1px}.input-group .form-control:last-child,.input-group-button:last-child .btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-button:last-child .btn{margin-left:-1px}.radio-group::before{display:table;content:\"\"}.radio-group::after{display:table;clear:both;content:\"\"}.radio-label{float:left;padding:6px 16px 6px 36px;margin-left:-1px;font-size:14px;line-height:20px;color:#24292e;cursor:pointer;border:1px solid #d1d5da}:checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.radio-label:first-of-type{margin-left:0;border-top-left-radius:3px;border-bottom-left-radius:3px}.radio-label:last-of-type{border-top-right-radius:3px;border-bottom-right-radius:3px}.radio-input{z-index:3;float:left;margin:10px -32px 0 16px}.container-sm{max-width:544px;margin-right:auto;margin-left:auto}.container-md{max-width:768px;margin-right:auto;margin-left:auto}.container-lg{max-width:1012px;margin-right:auto;margin-left:auto}.container-xl{max-width:1280px;margin-right:auto;margin-left:auto}.col-1{width:8.33333%}.col-2{width:16.66667%}.col-3{width:25%}.col-4{width:33.33333%}.col-5{width:41.66667%}.col-6{width:50%}.col-7{width:58.33333%}.col-8{width:66.66667%}.col-9{width:75%}.col-10{width:83.33333%}.col-11{width:91.66667%}.col-12{width:100%}@media (min-width: 544px){.col-sm-1{width:8.33333%}.col-sm-2{width:16.66667%}.col-sm-3{width:25%}.col-sm-4{width:33.33333%}.col-sm-5{width:41.66667%}.col-sm-6{width:50%}.col-sm-7{width:58.33333%}.col-sm-8{width:66.66667%}.col-sm-9{width:75%}.col-sm-10{width:83.33333%}.col-sm-11{width:91.66667%}.col-sm-12{width:100%}}@media (min-width: 768px){.col-md-1{width:8.33333%}.col-md-2{width:16.66667%}.col-md-3{width:25%}.col-md-4{width:33.33333%}.col-md-5{width:41.66667%}.col-md-6{width:50%}.col-md-7{width:58.33333%}.col-md-8{width:66.66667%}.col-md-9{width:75%}.col-md-10{width:83.33333%}.col-md-11{width:91.66667%}.col-md-12{width:100%}}@media (min-width: 1012px){.col-lg-1{width:8.33333%}.col-lg-2{width:16.66667%}.col-lg-3{width:25%}.col-lg-4{width:33.33333%}.col-lg-5{width:41.66667%}.col-lg-6{width:50%}.col-lg-7{width:58.33333%}.col-lg-8{width:66.66667%}.col-lg-9{width:75%}.col-lg-10{width:83.33333%}.col-lg-11{width:91.66667%}.col-lg-12{width:100%}}@media (min-width: 1280px){.col-xl-1{width:8.33333%}.col-xl-2{width:16.66667%}.col-xl-3{width:25%}.col-xl-4{width:33.33333%}.col-xl-5{width:41.66667%}.col-xl-6{width:50%}.col-xl-7{width:58.33333%}.col-xl-8{width:66.66667%}.col-xl-9{width:75%}.col-xl-10{width:83.33333%}.col-xl-11{width:91.66667%}.col-xl-12{width:100%}}.gutter{margin-right:-16px;margin-left:-16px}.gutter>[class*=\"col-\"]{padding-right:16px !important;padding-left:16px !important}.gutter-condensed{margin-right:-8px;margin-left:-8px}.gutter-condensed>[class*=\"col-\"]{padding-right:8px !important;padding-left:8px !important}.gutter-spacious{margin-right:-24px;margin-left:-24px}.gutter-spacious>[class*=\"col-\"]{padding-right:24px !important;padding-left:24px !important}@media (min-width: 544px){.gutter-sm{margin-right:-16px;margin-left:-16px}.gutter-sm>[class*=\"col-\"]{padding-right:16px !important;padding-left:16px !important}.gutter-sm-condensed{margin-right:-8px;margin-left:-8px}.gutter-sm-condensed>[class*=\"col-\"]{padding-right:8px !important;padding-left:8px !important}.gutter-sm-spacious{margin-right:-24px;margin-left:-24px}.gutter-sm-spacious>[class*=\"col-\"]{padding-right:24px !important;padding-left:24px !important}}@media (min-width: 768px){.gutter-md{margin-right:-16px;margin-left:-16px}.gutter-md>[class*=\"col-\"]{padding-right:16px !important;padding-left:16px !important}.gutter-md-condensed{margin-right:-8px;margin-left:-8px}.gutter-md-condensed>[class*=\"col-\"]{padding-right:8px !important;padding-left:8px !important}.gutter-md-spacious{margin-right:-24px;margin-left:-24px}.gutter-md-spacious>[class*=\"col-\"]{padding-right:24px !important;padding-left:24px !important}}@media (min-width: 1012px){.gutter-lg{margin-right:-16px;margin-left:-16px}.gutter-lg>[class*=\"col-\"]{padding-right:16px !important;padding-left:16px !important}.gutter-lg-condensed{margin-right:-8px;margin-left:-8px}.gutter-lg-condensed>[class*=\"col-\"]{padding-right:8px !important;padding-left:8px !important}.gutter-lg-spacious{margin-right:-24px;margin-left:-24px}.gutter-lg-spacious>[class*=\"col-\"]{padding-right:24px !important;padding-left:24px !important}}@media (min-width: 1280px){.gutter-xl{margin-right:-16px;margin-left:-16px}.gutter-xl>[class*=\"col-\"]{padding-right:16px !important;padding-left:16px !important}.gutter-xl-condensed{margin-right:-8px;margin-left:-8px}.gutter-xl-condensed>[class*=\"col-\"]{padding-right:8px !important;padding-left:8px !important}.gutter-xl-spacious{margin-right:-24px;margin-left:-24px}.gutter-xl-spacious>[class*=\"col-\"]{padding-right:24px !important;padding-left:24px !important}}.offset-1{margin-left:8.33333% !important}.offset-2{margin-left:16.66667% !important}.offset-3{margin-left:25% !important}.offset-4{margin-left:33.33333% !important}.offset-5{margin-left:41.66667% !important}.offset-6{margin-left:50% !important}.offset-7{margin-left:58.33333% !important}.offset-8{margin-left:66.66667% !important}.offset-9{margin-left:75% !important}.offset-10{margin-left:83.33333% !important}.offset-11{margin-left:91.66667% !important}@media (min-width: 544px){.offset-sm-1{margin-left:8.33333% !important}.offset-sm-2{margin-left:16.66667% !important}.offset-sm-3{margin-left:25% !important}.offset-sm-4{margin-left:33.33333% !important}.offset-sm-5{margin-left:41.66667% !important}.offset-sm-6{margin-left:50% !important}.offset-sm-7{margin-left:58.33333% !important}.offset-sm-8{margin-left:66.66667% !important}.offset-sm-9{margin-left:75% !important}.offset-sm-10{margin-left:83.33333% !important}.offset-sm-11{margin-left:91.66667% !important}}@media (min-width: 768px){.offset-md-1{margin-left:8.33333% !important}.offset-md-2{margin-left:16.66667% !important}.offset-md-3{margin-left:25% !important}.offset-md-4{margin-left:33.33333% !important}.offset-md-5{margin-left:41.66667% !important}.offset-md-6{margin-left:50% !important}.offset-md-7{margin-left:58.33333% !important}.offset-md-8{margin-left:66.66667% !important}.offset-md-9{margin-left:75% !important}.offset-md-10{margin-left:83.33333% !important}.offset-md-11{margin-left:91.66667% !important}}@media (min-width: 1012px){.offset-lg-1{margin-left:8.33333% !important}.offset-lg-2{margin-left:16.66667% !important}.offset-lg-3{margin-left:25% !important}.offset-lg-4{margin-left:33.33333% !important}.offset-lg-5{margin-left:41.66667% !important}.offset-lg-6{margin-left:50% !important}.offset-lg-7{margin-left:58.33333% !important}.offset-lg-8{margin-left:66.66667% !important}.offset-lg-9{margin-left:75% !important}.offset-lg-10{margin-left:83.33333% !important}.offset-lg-11{margin-left:91.66667% !important}}@media (min-width: 1280px){.offset-xl-1{margin-left:8.33333% !important}.offset-xl-2{margin-left:16.66667% !important}.offset-xl-3{margin-left:25% !important}.offset-xl-4{margin-left:33.33333% !important}.offset-xl-5{margin-left:41.66667% !important}.offset-xl-6{margin-left:50% !important}.offset-xl-7{margin-left:58.33333% !important}.offset-xl-8{margin-left:66.66667% !important}.offset-xl-9{margin-left:75% !important}.offset-xl-10{margin-left:83.33333% !important}.offset-xl-11{margin-left:91.66667% !important}}.menu{margin-bottom:15px;list-style:none;background-color:#fff;border:1px solid #d1d5da;border-radius:3px}.menu-item{position:relative;display:block;padding:8px 10px;border-bottom:1px #e1e4e8 solid}.menu-item:first-child{border-top:0;border-top-left-radius:2px;border-top-right-radius:2px}.menu-item:first-child::before{border-top-left-radius:2px}.menu-item:last-child{border-bottom:0;border-bottom-right-radius:2px;border-bottom-left-radius:2px}.menu-item:last-child::before{border-bottom-left-radius:2px}.menu-item:hover{text-decoration:none;background-color:#f6f8fa}.menu-item.selected,.menu-item[aria-selected=true],.menu-item[aria-current]{font-weight:600;color:#24292e;cursor:default;background-color:#fff}.menu-item.selected::before,.menu-item[aria-selected=true]::before,.menu-item[aria-current]::before{position:absolute;top:0;bottom:0;left:0;width:2px;content:\"\";background-color:#e36209}.menu-item .octicon{width:16px;margin-right:5px;color:#24292e;text-align:center}.menu-item .Counter{float:right;margin-left:5px}.menu-item .menu-warning{float:right;color:#86181d}.menu-item .avatar{float:left;margin-right:5px}.menu-item.alert .Counter{color:#cb2431}.menu-heading{display:block;padding:8px 10px;margin-top:0;margin-bottom:0;font-size:13px;font-weight:600;line-height:20px;color:#586069;background-color:#f3f5f8;border-bottom:1px #e1e4e8 solid}.menu-heading:hover{text-decoration:none}.menu-heading:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.menu-heading:last-child{border-bottom:0;border-bottom-right-radius:2px;border-bottom-left-radius:2px}.tabnav{margin-top:0;margin-bottom:15px;border-bottom:1px solid #d1d5da}.tabnav .Counter{margin-left:5px}.tabnav-tabs{margin-bottom:-1px}.tabnav-tab{display:inline-block;padding:8px 12px;font-size:14px;line-height:20px;color:#586069;text-decoration:none;background-color:transparent;border:1px solid transparent;border-bottom:0}.tabnav-tab.selected,.tabnav-tab[aria-selected=true],.tabnav-tab[aria-current]{color:#24292e;background-color:#fff;border-color:#d1d5da;border-radius:3px 3px 0 0}.tabnav-tab:hover,.tabnav-tab:focus{color:#24292e;text-decoration:none}.tabnav-extra{display:inline-block;padding-top:10px;margin-left:10px;font-size:12px;color:#586069}.tabnav-extra>.octicon{margin-right:2px}a.tabnav-extra:hover{color:#0366d6;text-decoration:none}.tabnav-btn{margin-left:10px}.filter-list{list-style-type:none}.filter-list.small .filter-item{padding:4px 10px;margin:0 0 2px;font-size:12px}.filter-list.pjax-active .filter-item{color:#586069;background-color:transparent}.filter-list.pjax-active .filter-item.pjax-active{color:#fff;background-color:#0366d6}.filter-item{position:relative;display:block;padding:8px 10px;margin-bottom:5px;overflow:hidden;font-size:14px;color:#586069;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;cursor:pointer;border-radius:3px}.filter-item:hover{text-decoration:none;background-color:#eaecef}.filter-item.selected,.filter-item[aria-selected=true],.filter-item[aria-current]{color:#fff;background-color:#0366d6}.filter-item .count{float:right;font-weight:600}.filter-item .bar{position:absolute;top:2px;right:0;bottom:2px;z-index:-1;display:inline-block;background-color:#eff3f6}.SideNav{background-color:#fafbfc}.SideNav-item{position:relative;display:block;width:100%;padding:16px;color:#586069;text-align:left;background-color:transparent;border:0;border-top:1px #e1e4e8 solid}.SideNav-item:first-child{border-top:0}.SideNav-item:last-child{box-shadow:0 1px 0 #e1e4e8}.SideNav-item::before{position:absolute;top:0;bottom:0;left:0;z-index:1;width:3px;pointer-events:none;content:\"\"}.SideNav-item:hover,.SideNav-item:focus{color:#24292e;text-decoration:none;background-color:#f6f8fa;outline:none}.SideNav-item:hover::before,.SideNav-item:focus::before{background-color:#d1d5da}.SideNav-item:active{background-color:#fff}.SideNav-item[aria-current=\"page\"],.SideNav-item[aria-selected=\"true\"]{font-weight:500;color:#24292e;background-color:#fff}.SideNav-item[aria-current=\"page\"]::before,.SideNav-item[aria-selected=\"true\"]::before{background-color:#e36209}.SideNav-icon{width:16px;color:#6a737d}.SideNav-subItem{position:relative;display:block;width:100%;padding:4px 0;color:#0366d6;text-align:left;background-color:transparent;border:0}.SideNav-subItem:hover,.SideNav-subItem:focus{color:#24292e;text-decoration:none;outline:none}.SideNav-subItem[aria-current=\"page\"],.SideNav-subItem[aria-selected=\"true\"]{font-weight:500;color:#24292e}.subnav{margin-bottom:20px}.subnav::before{display:table;content:\"\"}.subnav::after{display:table;clear:both;content:\"\"}.subnav-bordered{padding-bottom:20px;border-bottom:1px solid #eaecef}.subnav-flush{margin-bottom:0}.subnav-item{position:relative;float:left;padding:6px 14px;font-weight:600;line-height:20px;color:#586069;border:1px #e1e4e8 solid}.subnav-item+.subnav-item{margin-left:-1px}.subnav-item:hover,.subnav-item:focus{text-decoration:none;background-color:#f6f8fa}.subnav-item.selected,.subnav-item[aria-selected=true],.subnav-item[aria-current]{z-index:2;color:#fff;background-color:#0366d6;border-color:#0366d6}.subnav-item:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.subnav-item:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.subnav-search{position:relative;margin-left:10px}.subnav-search-input{width:320px;padding-left:30px;color:#586069}.subnav-search-input-wide{width:500px}.subnav-search-icon{position:absolute;top:9px;left:8px;display:block;color:#c6cbd1;text-align:center;pointer-events:none}.subnav-search-context .btn{color:#444d56;border-top-right-radius:0;border-bottom-right-radius:0}.subnav-search-context .btn:hover,.subnav-search-context .btn:focus,.subnav-search-context .btn:active,.subnav-search-context .btn.selected{z-index:2}.subnav-search-context+.subnav-search{margin-left:-1px}.subnav-search-context+.subnav-search .subnav-search-input{border-top-left-radius:0;border-bottom-left-radius:0}.subnav-search-context .select-menu-modal-holder{z-index:30}.subnav-search-context .select-menu-modal{width:220px}.subnav-search-context .select-menu-item-icon{color:inherit}.subnav-spacer-right{padding-right:10px}.UnderlineNav{display:flex;overflow-x:auto;overflow-y:hidden;border-bottom:1px #e1e4e8 solid;justify-content:space-between}.UnderlineNav-body{display:flex}.UnderlineNav-item{padding:16px 8px;margin-right:16px;font-size:14px;line-height:1.5;color:#586069;text-align:center;border:0;border-bottom:2px solid transparent}.UnderlineNav-item:hover,.UnderlineNav-item:focus{color:#24292e;text-decoration:none;border-bottom-color:#d1d5da;transition:0.2s ease}.UnderlineNav-item:hover .UnderlineNav-octicon,.UnderlineNav-item:focus .UnderlineNav-octicon{color:#6a737d}.UnderlineNav-item.selected,.UnderlineNav-item[role=tab][aria-selected=true],.UnderlineNav-item[aria-current]{font-weight:600;color:#24292e;border-bottom-color:#e36209}.UnderlineNav-item.selected .UnderlineNav-octicon,.UnderlineNav-item[role=tab][aria-selected=true] .UnderlineNav-octicon,.UnderlineNav-item[aria-current] .UnderlineNav-octicon{color:#6a737d}.UnderlineNav--right{justify-content:flex-end}.UnderlineNav--right .UnderlineNav-item{margin-right:0;margin-left:16px}.UnderlineNav--right .UnderlineNav-actions{flex:1 1 auto}.UnderlineNav-actions{align-self:center}.UnderlineNav--full{display:block}.UnderlineNav-octicon{color:#959da5}.UnderlineNav-container{display:flex;justify-content:space-between}.pagination::before{display:table;content:\"\"}.pagination::after{display:table;clear:both;content:\"\"}.pagination a,.pagination span,.pagination em{position:relative;float:left;padding:7px 12px;margin-left:-1px;font-size:13px;font-style:normal;font-weight:600;color:#0366d6;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:#fff;border:1px solid #e1e4e8}.pagination a:first-child,.pagination span:first-child,.pagination em:first-child{margin-left:0;border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination a:last-child,.pagination span:last-child,.pagination em:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.pagination a:hover,.pagination a:focus,.pagination span:hover,.pagination span:focus,.pagination em:hover,.pagination em:focus{z-index:2;text-decoration:none;background-color:#eff3f6;border-color:#e1e4e8}.pagination .selected{z-index:3}.pagination .current,.pagination .current:hover,.pagination [aria-current],.pagination [aria-current]:hover{z-index:3;color:#fff;background-color:#0366d6;border-color:#0366d6}.pagination .gap,.pagination .disabled,.pagination [aria-disabled=true],.pagination .gap:hover,.pagination .disabled:hover,.pagination [aria-disabled=true]:hover{color:#d1d5da;cursor:default;background-color:#fafbfc}.paginate-container{margin-top:20px;margin-bottom:15px;text-align:center}.paginate-container .pagination{display:inline-block}.tooltipped{position:relative}.tooltipped::after{position:absolute;z-index:1000000;display:none;padding:.5em .75em;font:normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,\"Segoe UI\",Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\";-webkit-font-smoothing:subpixel-antialiased;color:#fff;text-align:center;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-wrap:break-word;white-space:pre;pointer-events:none;content:attr(aria-label);background:#1b1f23;border-radius:3px;opacity:0}.tooltipped::before{position:absolute;z-index:1000001;display:none;width:0;height:0;color:#1b1f23;pointer-events:none;content:\"\";border:6px solid transparent;opacity:0}@keyframes tooltip-appear{from{opacity:0}to{opacity:1}}.tooltipped:hover::before,.tooltipped:hover::after,.tooltipped:active::before,.tooltipped:active::after,.tooltipped:focus::before,.tooltipped:focus::after{display:inline-block;text-decoration:none;animation-name:tooltip-appear;animation-duration:.1s;animation-fill-mode:forwards;animation-timing-function:ease-in;animation-delay:.4s}.tooltipped-no-delay:hover::before,.tooltipped-no-delay:hover::after,.tooltipped-no-delay:active::before,.tooltipped-no-delay:active::after,.tooltipped-no-delay:focus::before,.tooltipped-no-delay:focus::after{animation-delay:0s}.tooltipped-multiline:hover::after,.tooltipped-multiline:active::after,.tooltipped-multiline:focus::after{display:table-cell}.tooltipped-s::after,.tooltipped-se::after,.tooltipped-sw::after{top:100%;right:50%;margin-top:6px}.tooltipped-s::before,.tooltipped-se::before,.tooltipped-sw::before{top:auto;right:50%;bottom:-7px;margin-right:-6px;border-bottom-color:#1b1f23}.tooltipped-se::after{right:auto;left:50%;margin-left:-16px}.tooltipped-sw::after{margin-right:-16px}.tooltipped-n::after,.tooltipped-ne::after,.tooltipped-nw::after{right:50%;bottom:100%;margin-bottom:6px}.tooltipped-n::before,.tooltipped-ne::before,.tooltipped-nw::before{top:-7px;right:50%;bottom:auto;margin-right:-6px;border-top-color:#1b1f23}.tooltipped-ne::after{right:auto;left:50%;margin-left:-16px}.tooltipped-nw::after{margin-right:-16px}.tooltipped-s::after,.tooltipped-n::after{transform:translateX(50%)}.tooltipped-w::after{right:100%;bottom:50%;margin-right:6px;transform:translateY(50%)}.tooltipped-w::before{top:50%;bottom:50%;left:-7px;margin-top:-6px;border-left-color:#1b1f23}.tooltipped-e::after{bottom:50%;left:100%;margin-left:6px;transform:translateY(50%)}.tooltipped-e::before{top:50%;right:-7px;bottom:50%;margin-top:-6px;border-right-color:#1b1f23}.tooltipped-align-right-1::after,.tooltipped-align-right-2::after{right:0;margin-right:0}.tooltipped-align-right-1::before{right:10px}.tooltipped-align-right-2::before{right:15px}.tooltipped-align-left-1::after,.tooltipped-align-left-2::after{left:0;margin-left:0}.tooltipped-align-left-1::before{left:5px}.tooltipped-align-left-2::before{left:10px}.tooltipped-multiline::after{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;word-wrap:break-word;white-space:pre-line;border-collapse:separate}.tooltipped-multiline.tooltipped-s::after,.tooltipped-multiline.tooltipped-n::after{right:auto;left:50%;transform:translateX(-50%)}.tooltipped-multiline.tooltipped-w::after,.tooltipped-multiline.tooltipped-e::after{right:100%}@media screen and (min-width: 0\\0){.tooltipped-multiline::after{width:250px}}.tooltipped-sticky::before,.tooltipped-sticky::after{display:inline-block}.tooltipped-sticky.tooltipped-multiline::after{display:table-cell}.css-truncate.css-truncate-overflow,.css-truncate .css-truncate-overflow,.css-truncate.css-truncate-target,.css-truncate .css-truncate-target{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.css-truncate.css-truncate-target,.css-truncate .css-truncate-target{display:inline-block;max-width:125px;vertical-align:top}.css-truncate.expandable.zeroclipboard-is-hover .css-truncate-target,.css-truncate.expandable.zeroclipboard-is-hover.css-truncate-target,.css-truncate.expandable:hover .css-truncate-target,.css-truncate.expandable:hover.css-truncate-target{max-width:10000px !important}.anim-fade-in{animation-name:fade-in;animation-duration:1s;animation-timing-function:ease-in-out}.anim-fade-in.fast{animation-duration:300ms}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}.anim-fade-out{animation-name:fade-out;animation-duration:1s;animation-timing-function:ease-out}.anim-fade-out.fast{animation-duration:0.3s}@keyframes fade-out{0%{opacity:1}100%{opacity:0}}.anim-fade-up{opacity:0;animation-name:fade-up;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease-out;animation-delay:1s}@keyframes fade-up{0%{opacity:0.8;transform:translateY(100%)}100%{opacity:1;transform:translateY(0)}}.anim-fade-down{animation-name:fade-down;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease-in}@keyframes fade-down{0%{opacity:1;transform:translateY(0)}100%{opacity:0.5;transform:translateY(100%)}}.anim-grow-x{width:0%;animation-name:grow-x;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease;animation-delay:0.5s}@keyframes grow-x{to{width:100%}}.anim-shrink-x{animation-name:shrink-x;animation-duration:0.3s;animation-fill-mode:forwards;animation-timing-function:ease-in-out;animation-delay:0.5s}@keyframes shrink-x{to{width:0%}}.anim-scale-in{animation-name:scale-in;animation-duration:0.15s;animation-timing-function:cubic-bezier(0.2, 0, 0.13, 1.5)}@keyframes scale-in{0%{opacity:0;transform:scale(0.5)}100%{opacity:1;transform:scale(1)}}.anim-pulse{animation-name:pulse;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}@keyframes pulse{0%{opacity:0.3}10%{opacity:1}100%{opacity:0.3}}.anim-pulse-in{animation-name:pulse-in;animation-duration:0.5s}@keyframes pulse-in{0%{transform:scale3d(1, 1, 1)}50%{transform:scale3d(1.1, 1.1, 1.1)}100%{transform:scale3d(1, 1, 1)}}.hover-grow{transition:transform 0.3s;-webkit-backface-visibility:hidden;backface-visibility:hidden}.hover-grow:hover{transform:scale(1.025)}.border-x{border-right:1px #e1e4e8 solid !important;border-left:1px #e1e4e8 solid !important}.border-y{border-top:1px #e1e4e8 solid !important;border-bottom:1px #e1e4e8 solid !important}.border{border:1px #e1e4e8 solid !important}.border-0{border:0 !important}.border-top{border-top:1px #e1e4e8 solid !important}.border-right{border-right:1px #e1e4e8 solid !important}.border-bottom{border-bottom:1px #e1e4e8 solid !important}.border-left{border-left:1px #e1e4e8 solid !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.rounded-0{border-radius:0 !important}.rounded-1{border-radius:3px !important}.rounded-2{border-radius:6px !important}.rounded-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}@media (min-width: 544px){.border-sm{border:1px #e1e4e8 solid !important}.border-sm-0{border:0 !important}.border-sm-top{border-top:1px #e1e4e8 solid !important}.border-sm-right{border-right:1px #e1e4e8 solid !important}.border-sm-bottom{border-bottom:1px #e1e4e8 solid !important}.border-sm-left{border-left:1px #e1e4e8 solid !important}.border-sm-top-0{border-top:0 !important}.border-sm-right-0{border-right:0 !important}.border-sm-bottom-0{border-bottom:0 !important}.border-sm-left-0{border-left:0 !important}.rounded-sm-0{border-radius:0 !important}.rounded-sm-1{border-radius:3px !important}.rounded-sm-2{border-radius:6px !important}.rounded-sm-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-sm-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-sm-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-sm-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-sm-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-sm-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-sm-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-sm-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-sm-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-sm-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-sm-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-sm-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}@media (min-width: 768px){.border-md{border:1px #e1e4e8 solid !important}.border-md-0{border:0 !important}.border-md-top{border-top:1px #e1e4e8 solid !important}.border-md-right{border-right:1px #e1e4e8 solid !important}.border-md-bottom{border-bottom:1px #e1e4e8 solid !important}.border-md-left{border-left:1px #e1e4e8 solid !important}.border-md-top-0{border-top:0 !important}.border-md-right-0{border-right:0 !important}.border-md-bottom-0{border-bottom:0 !important}.border-md-left-0{border-left:0 !important}.rounded-md-0{border-radius:0 !important}.rounded-md-1{border-radius:3px !important}.rounded-md-2{border-radius:6px !important}.rounded-md-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-md-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-md-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-md-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-md-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-md-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-md-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-md-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-md-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-md-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-md-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-md-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}@media (min-width: 1012px){.border-lg{border:1px #e1e4e8 solid !important}.border-lg-0{border:0 !important}.border-lg-top{border-top:1px #e1e4e8 solid !important}.border-lg-right{border-right:1px #e1e4e8 solid !important}.border-lg-bottom{border-bottom:1px #e1e4e8 solid !important}.border-lg-left{border-left:1px #e1e4e8 solid !important}.border-lg-top-0{border-top:0 !important}.border-lg-right-0{border-right:0 !important}.border-lg-bottom-0{border-bottom:0 !important}.border-lg-left-0{border-left:0 !important}.rounded-lg-0{border-radius:0 !important}.rounded-lg-1{border-radius:3px !important}.rounded-lg-2{border-radius:6px !important}.rounded-lg-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-lg-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-lg-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-lg-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-lg-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-lg-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-lg-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-lg-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-lg-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-lg-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-lg-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-lg-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}@media (min-width: 1280px){.border-xl{border:1px #e1e4e8 solid !important}.border-xl-0{border:0 !important}.border-xl-top{border-top:1px #e1e4e8 solid !important}.border-xl-right{border-right:1px #e1e4e8 solid !important}.border-xl-bottom{border-bottom:1px #e1e4e8 solid !important}.border-xl-left{border-left:1px #e1e4e8 solid !important}.border-xl-top-0{border-top:0 !important}.border-xl-right-0{border-right:0 !important}.border-xl-bottom-0{border-bottom:0 !important}.border-xl-left-0{border-left:0 !important}.rounded-xl-0{border-radius:0 !important}.rounded-xl-1{border-radius:3px !important}.rounded-xl-2{border-radius:6px !important}.rounded-xl-top-0{border-top-left-radius:0 !important;border-top-right-radius:0 !important}.rounded-xl-top-1{border-top-left-radius:3px !important;border-top-right-radius:3px !important}.rounded-xl-top-2{border-top-left-radius:6px !important;border-top-right-radius:6px !important}.rounded-xl-right-0{border-top-right-radius:0 !important;border-bottom-right-radius:0 !important}.rounded-xl-right-1{border-top-right-radius:3px !important;border-bottom-right-radius:3px !important}.rounded-xl-right-2{border-top-right-radius:6px !important;border-bottom-right-radius:6px !important}.rounded-xl-bottom-0{border-bottom-right-radius:0 !important;border-bottom-left-radius:0 !important}.rounded-xl-bottom-1{border-bottom-right-radius:3px !important;border-bottom-left-radius:3px !important}.rounded-xl-bottom-2{border-bottom-right-radius:6px !important;border-bottom-left-radius:6px !important}.rounded-xl-left-0{border-bottom-left-radius:0 !important;border-top-left-radius:0 !important}.rounded-xl-left-1{border-bottom-left-radius:3px !important;border-top-left-radius:3px !important}.rounded-xl-left-2{border-bottom-left-radius:6px !important;border-top-left-radius:6px !important}}.circle{border-radius:50% !important}.border-dashed{border-style:dashed !important}.border-blue{border-color:#0366d6 !important}.border-blue-light{border-color:#c8e1ff !important}.border-green{border-color:#34d058 !important}.border-green-light{border-color:#a2cbac !important}.border-red{border-color:#d73a49 !important}.border-red-light{border-color:#cea0a5 !important}.border-purple{border-color:#6f42c1 !important}.border-yellow{border-color:#d9d0a5 !important}.border-gray-light{border-color:#eaecef !important}.border-gray-dark{border-color:#d1d5da !important}.border-black-fade{border-color:rgba(27,31,35,0.15) !important}.border-white-fade{border-color:rgba(255,255,255,0.15) !important}.border-white-fade-15{border-color:rgba(255,255,255,0.15) !important}.border-white-fade-30{border-color:rgba(255,255,255,0.3) !important}.border-white-fade-50{border-color:rgba(255,255,255,0.5) !important}.border-white-fade-70{border-color:rgba(255,255,255,0.7) !important}.border-white-fade-85{border-color:rgba(255,255,255,0.85) !important}.box-shadow{box-shadow:0 1px 1px rgba(27,31,35,0.1) !important}.box-shadow-medium{box-shadow:0 1px 5px rgba(27,31,35,0.15) !important}.box-shadow-large{box-shadow:0 1px 15px rgba(27,31,35,0.15) !important}.box-shadow-extra-large{box-shadow:0 10px 50px rgba(27,31,35,0.07) !important}.box-shadow-none{box-shadow:none !important}.bg-white{background-color:#fff !important}.bg-blue{background-color:#0366d6 !important}.bg-blue-light{background-color:#f1f8ff !important}.bg-gray-dark{background-color:#24292e !important}.bg-gray{background-color:#f6f8fa !important}.bg-gray-light{background-color:#fafbfc !important}.bg-green{background-color:#28a745 !important}.bg-green-light{background-color:#dcffe4 !important}.bg-red{background-color:#d73a49 !important}.bg-red-light{background-color:#ffdce0 !important}.bg-yellow{background-color:#ffd33d !important}.bg-yellow-light{background-color:#fff5b1 !important}.bg-yellow-dark{background-color:#dbab09 !important}.bg-purple{background-color:#6f42c1 !important}.bg-pink{background-color:#ea4aaa !important}.bg-purple-light{background-color:#f5f0ff !important}.color-gray-0{color:#fafbfc !important}.bg-gray-0{background-color:#fafbfc !important}.color-gray-1{color:#f6f8fa !important}.bg-gray-1{background-color:#f6f8fa !important}.color-gray-2{color:#e1e4e8 !important}.bg-gray-2{background-color:#e1e4e8 !important}.color-gray-3{color:#d1d5da !important}.bg-gray-3{background-color:#d1d5da !important}.color-gray-4{color:#959da5 !important}.bg-gray-4{background-color:#959da5 !important}.color-gray-5{color:#6a737d !important}.bg-gray-5{background-color:#6a737d !important}.color-gray-6{color:#586069 !important}.bg-gray-6{background-color:#586069 !important}.color-gray-7{color:#444d56 !important}.bg-gray-7{background-color:#444d56 !important}.color-gray-8{color:#2f363d !important}.bg-gray-8{background-color:#2f363d !important}.color-gray-9{color:#24292e !important}.bg-gray-9{background-color:#24292e !important}.color-blue-0{color:#f1f8ff !important}.bg-blue-0{background-color:#f1f8ff !important}.color-blue-1{color:#dbedff !important}.bg-blue-1{background-color:#dbedff !important}.color-blue-2{color:#c8e1ff !important}.bg-blue-2{background-color:#c8e1ff !important}.color-blue-3{color:#79b8ff !important}.bg-blue-3{background-color:#79b8ff !important}.color-blue-4{color:#2188ff !important}.bg-blue-4{background-color:#2188ff !important}.color-blue-5{color:#0366d6 !important}.bg-blue-5{background-color:#0366d6 !important}.color-blue-6{color:#005cc5 !important}.bg-blue-6{background-color:#005cc5 !important}.color-blue-7{color:#044289 !important}.bg-blue-7{background-color:#044289 !important}.color-blue-8{color:#032f62 !important}.bg-blue-8{background-color:#032f62 !important}.color-blue-9{color:#05264c !important}.bg-blue-9{background-color:#05264c !important}.color-green-0{color:#f0fff4 !important}.bg-green-0{background-color:#f0fff4 !important}.color-green-1{color:#dcffe4 !important}.bg-green-1{background-color:#dcffe4 !important}.color-green-2{color:#bef5cb !important}.bg-green-2{background-color:#bef5cb !important}.color-green-3{color:#85e89d !important}.bg-green-3{background-color:#85e89d !important}.color-green-4{color:#34d058 !important}.bg-green-4{background-color:#34d058 !important}.color-green-5{color:#28a745 !important}.bg-green-5{background-color:#28a745 !important}.color-green-6{color:#22863a !important}.bg-green-6{background-color:#22863a !important}.color-green-7{color:#176f2c !important}.bg-green-7{background-color:#176f2c !important}.color-green-8{color:#165c26 !important}.bg-green-8{background-color:#165c26 !important}.color-green-9{color:#144620 !important}.bg-green-9{background-color:#144620 !important}.color-yellow-0{color:#fffdef !important}.bg-yellow-0{background-color:#fffdef !important}.color-yellow-1{color:#fffbdd !important}.bg-yellow-1{background-color:#fffbdd !important}.color-yellow-2{color:#fff5b1 !important}.bg-yellow-2{background-color:#fff5b1 !important}.color-yellow-3{color:#ffea7f !important}.bg-yellow-3{background-color:#ffea7f !important}.color-yellow-4{color:#ffdf5d !important}.bg-yellow-4{background-color:#ffdf5d !important}.color-yellow-5{color:#ffd33d !important}.bg-yellow-5{background-color:#ffd33d !important}.color-yellow-6{color:#f9c513 !important}.bg-yellow-6{background-color:#f9c513 !important}.color-yellow-7{color:#dbab09 !important}.bg-yellow-7{background-color:#dbab09 !important}.color-yellow-8{color:#b08800 !important}.bg-yellow-8{background-color:#b08800 !important}.color-yellow-9{color:#735c0f !important}.bg-yellow-9{background-color:#735c0f !important}.color-orange-0{color:#fff8f2 !important}.bg-orange-0{background-color:#fff8f2 !important}.color-orange-1{color:#ffebda !important}.bg-orange-1{background-color:#ffebda !important}.color-orange-2{color:#ffd1ac !important}.bg-orange-2{background-color:#ffd1ac !important}.color-orange-3{color:#ffab70 !important}.bg-orange-3{background-color:#ffab70 !important}.color-orange-4{color:#fb8532 !important}.bg-orange-4{background-color:#fb8532 !important}.color-orange-5{color:#f66a0a !important}.bg-orange-5{background-color:#f66a0a !important}.color-orange-6{color:#e36209 !important}.bg-orange-6{background-color:#e36209 !important}.color-orange-7{color:#d15704 !important}.bg-orange-7{background-color:#d15704 !important}.color-orange-8{color:#c24e00 !important}.bg-orange-8{background-color:#c24e00 !important}.color-orange-9{color:#a04100 !important}.bg-orange-9{background-color:#a04100 !important}.color-red-0{color:#ffeef0 !important}.bg-red-0{background-color:#ffeef0 !important}.color-red-1{color:#ffdce0 !important}.bg-red-1{background-color:#ffdce0 !important}.color-red-2{color:#fdaeb7 !important}.bg-red-2{background-color:#fdaeb7 !important}.color-red-3{color:#f97583 !important}.bg-red-3{background-color:#f97583 !important}.color-red-4{color:#ea4a5a !important}.bg-red-4{background-color:#ea4a5a !important}.color-red-5{color:#d73a49 !important}.bg-red-5{background-color:#d73a49 !important}.color-red-6{color:#cb2431 !important}.bg-red-6{background-color:#cb2431 !important}.color-red-7{color:#b31d28 !important}.bg-red-7{background-color:#b31d28 !important}.color-red-8{color:#9e1c23 !important}.bg-red-8{background-color:#9e1c23 !important}.color-red-9{color:#86181d !important}.bg-red-9{background-color:#86181d !important}.color-purple-0{color:#f5f0ff !important}.bg-purple-0{background-color:#f5f0ff !important}.color-purple-1{color:#e6dcfd !important}.bg-purple-1{background-color:#e6dcfd !important}.color-purple-2{color:#d1bcf9 !important}.bg-purple-2{background-color:#d1bcf9 !important}.color-purple-3{color:#b392f0 !important}.bg-purple-3{background-color:#b392f0 !important}.color-purple-4{color:#8a63d2 !important}.bg-purple-4{background-color:#8a63d2 !important}.color-purple-5{color:#6f42c1 !important}.bg-purple-5{background-color:#6f42c1 !important}.color-purple-6{color:#5a32a3 !important}.bg-purple-6{background-color:#5a32a3 !important}.color-purple-7{color:#4c2889 !important}.bg-purple-7{background-color:#4c2889 !important}.color-purple-8{color:#3a1d6e !important}.bg-purple-8{background-color:#3a1d6e !important}.color-purple-9{color:#29134e !important}.bg-purple-9{background-color:#29134e !important}.color-pink-0{color:#ffeef8 !important}.bg-pink-0{background-color:#ffeef8 !important}.color-pink-1{color:#fedbf0 !important}.bg-pink-1{background-color:#fedbf0 !important}.color-pink-2{color:#f9b3dd !important}.bg-pink-2{background-color:#f9b3dd !important}.color-pink-3{color:#f692ce !important}.bg-pink-3{background-color:#f692ce !important}.color-pink-4{color:#ec6cb9 !important}.bg-pink-4{background-color:#ec6cb9 !important}.color-pink-5{color:#ea4aaa !important}.bg-pink-5{background-color:#ea4aaa !important}.color-pink-6{color:#d03592 !important}.bg-pink-6{background-color:#d03592 !important}.color-pink-7{color:#b93a86 !important}.bg-pink-7{background-color:#b93a86 !important}.color-pink-8{color:#99306f !important}.bg-pink-8{background-color:#99306f !important}.color-pink-9{color:#6d224f !important}.bg-pink-9{background-color:#6d224f !important}.bg-shade-gradient{background-image:linear-gradient(180deg, rgba(27,31,35,0.065), rgba(27,31,35,0)) !important;background-repeat:no-repeat !important;background-size:100% 200px !important}.text-blue{color:#0366d6 !important}.text-red{color:#cb2431 !important}.text-gray-light{color:#6a737d !important}.text-gray{color:#586069 !important}.text-gray-dark{color:#24292e !important}.text-green{color:#28a745 !important}.text-yellow{color:#b08800 !important}.text-orange{color:#a04100 !important}.text-orange-light{color:#e36209 !important}.text-purple{color:#6f42c1 !important}.text-pink{color:#ea4aaa !important}.text-white{color:#fff !important}.text-inherit{color:inherit !important}.link-gray{color:#586069 !important}.link-gray:hover{color:#0366d6 !important}.link-gray-dark{color:#24292e !important}.link-gray-dark:hover{color:#0366d6 !important}.link-hover-blue:hover{color:#0366d6 !important}.muted-link{color:#586069 !important}.muted-link:hover{color:#0366d6 !important;text-decoration:none}.details-overlay[open]>summary::before{position:fixed;top:0;right:0;bottom:0;left:0;z-index:80;display:block;cursor:default;content:\" \";background:transparent}.details-overlay-dark[open]>summary::before{z-index:99;background:rgba(27,31,35,0.5)}.details-reset>summary{list-style:none}.details-reset>summary::before{display:none}.details-reset>summary::-webkit-details-marker{display:none}.flex-row{flex-direction:row !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column{flex-direction:column !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-justify-start{justify-content:flex-start !important}.flex-justify-end{justify-content:flex-end !important}.flex-justify-center{justify-content:center !important}.flex-justify-between{justify-content:space-between !important}.flex-justify-around{justify-content:space-around !important}.flex-items-start{align-items:flex-start !important}.flex-items-end{align-items:flex-end !important}.flex-items-center{align-items:center !important}.flex-items-baseline{align-items:baseline !important}.flex-items-stretch{align-items:stretch !important}.flex-content-start{align-content:flex-start !important}.flex-content-end{align-content:flex-end !important}.flex-content-center{align-content:center !important}.flex-content-between{align-content:space-between !important}.flex-content-around{align-content:space-around !important}.flex-content-stretch{align-content:stretch !important}.flex-1{flex:1 !important}.flex-auto{flex:auto !important}.flex-grow-0{flex-grow:0 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-self-auto{align-self:auto !important}.flex-self-start{align-self:flex-start !important}.flex-self-end{align-self:flex-end !important}.flex-self-center{align-self:center !important}.flex-self-baseline{align-self:baseline !important}.flex-self-stretch{align-self:stretch !important}.flex-order-1{order:1 !important}.flex-order-2{order:2 !important}.flex-order-none{order:inherit !important}@media (min-width: 544px){.flex-sm-row{flex-direction:row !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column{flex-direction:column !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-justify-start{justify-content:flex-start !important}.flex-sm-justify-end{justify-content:flex-end !important}.flex-sm-justify-center{justify-content:center !important}.flex-sm-justify-between{justify-content:space-between !important}.flex-sm-justify-around{justify-content:space-around !important}.flex-sm-items-start{align-items:flex-start !important}.flex-sm-items-end{align-items:flex-end !important}.flex-sm-items-center{align-items:center !important}.flex-sm-items-baseline{align-items:baseline !important}.flex-sm-items-stretch{align-items:stretch !important}.flex-sm-content-start{align-content:flex-start !important}.flex-sm-content-end{align-content:flex-end !important}.flex-sm-content-center{align-content:center !important}.flex-sm-content-between{align-content:space-between !important}.flex-sm-content-around{align-content:space-around !important}.flex-sm-content-stretch{align-content:stretch !important}.flex-sm-1{flex:1 !important}.flex-sm-auto{flex:auto !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-self-auto{align-self:auto !important}.flex-sm-self-start{align-self:flex-start !important}.flex-sm-self-end{align-self:flex-end !important}.flex-sm-self-center{align-self:center !important}.flex-sm-self-baseline{align-self:baseline !important}.flex-sm-self-stretch{align-self:stretch !important}.flex-sm-order-1{order:1 !important}.flex-sm-order-2{order:2 !important}.flex-sm-order-none{order:inherit !important}}@media (min-width: 768px){.flex-md-row{flex-direction:row !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column{flex-direction:column !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-justify-start{justify-content:flex-start !important}.flex-md-justify-end{justify-content:flex-end !important}.flex-md-justify-center{justify-content:center !important}.flex-md-justify-between{justify-content:space-between !important}.flex-md-justify-around{justify-content:space-around !important}.flex-md-items-start{align-items:flex-start !important}.flex-md-items-end{align-items:flex-end !important}.flex-md-items-center{align-items:center !important}.flex-md-items-baseline{align-items:baseline !important}.flex-md-items-stretch{align-items:stretch !important}.flex-md-content-start{align-content:flex-start !important}.flex-md-content-end{align-content:flex-end !important}.flex-md-content-center{align-content:center !important}.flex-md-content-between{align-content:space-between !important}.flex-md-content-around{align-content:space-around !important}.flex-md-content-stretch{align-content:stretch !important}.flex-md-1{flex:1 !important}.flex-md-auto{flex:auto !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-self-auto{align-self:auto !important}.flex-md-self-start{align-self:flex-start !important}.flex-md-self-end{align-self:flex-end !important}.flex-md-self-center{align-self:center !important}.flex-md-self-baseline{align-self:baseline !important}.flex-md-self-stretch{align-self:stretch !important}.flex-md-order-1{order:1 !important}.flex-md-order-2{order:2 !important}.flex-md-order-none{order:inherit !important}}@media (min-width: 1012px){.flex-lg-row{flex-direction:row !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column{flex-direction:column !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-justify-start{justify-content:flex-start !important}.flex-lg-justify-end{justify-content:flex-end !important}.flex-lg-justify-center{justify-content:center !important}.flex-lg-justify-between{justify-content:space-between !important}.flex-lg-justify-around{justify-content:space-around !important}.flex-lg-items-start{align-items:flex-start !important}.flex-lg-items-end{align-items:flex-end !important}.flex-lg-items-center{align-items:center !important}.flex-lg-items-baseline{align-items:baseline !important}.flex-lg-items-stretch{align-items:stretch !important}.flex-lg-content-start{align-content:flex-start !important}.flex-lg-content-end{align-content:flex-end !important}.flex-lg-content-center{align-content:center !important}.flex-lg-content-between{align-content:space-between !important}.flex-lg-content-around{align-content:space-around !important}.flex-lg-content-stretch{align-content:stretch !important}.flex-lg-1{flex:1 !important}.flex-lg-auto{flex:auto !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-self-auto{align-self:auto !important}.flex-lg-self-start{align-self:flex-start !important}.flex-lg-self-end{align-self:flex-end !important}.flex-lg-self-center{align-self:center !important}.flex-lg-self-baseline{align-self:baseline !important}.flex-lg-self-stretch{align-self:stretch !important}.flex-lg-order-1{order:1 !important}.flex-lg-order-2{order:2 !important}.flex-lg-order-none{order:inherit !important}}@media (min-width: 1280px){.flex-xl-row{flex-direction:row !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column{flex-direction:column !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-justify-start{justify-content:flex-start !important}.flex-xl-justify-end{justify-content:flex-end !important}.flex-xl-justify-center{justify-content:center !important}.flex-xl-justify-between{justify-content:space-between !important}.flex-xl-justify-around{justify-content:space-around !important}.flex-xl-items-start{align-items:flex-start !important}.flex-xl-items-end{align-items:flex-end !important}.flex-xl-items-center{align-items:center !important}.flex-xl-items-baseline{align-items:baseline !important}.flex-xl-items-stretch{align-items:stretch !important}.flex-xl-content-start{align-content:flex-start !important}.flex-xl-content-end{align-content:flex-end !important}.flex-xl-content-center{align-content:center !important}.flex-xl-content-between{align-content:space-between !important}.flex-xl-content-around{align-content:space-around !important}.flex-xl-content-stretch{align-content:stretch !important}.flex-xl-1{flex:1 !important}.flex-xl-auto{flex:auto !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-self-auto{align-self:auto !important}.flex-xl-self-start{align-self:flex-start !important}.flex-xl-self-end{align-self:flex-end !important}.flex-xl-self-center{align-self:center !important}.flex-xl-self-baseline{align-self:baseline !important}.flex-xl-self-stretch{align-self:stretch !important}.flex-xl-order-1{order:1 !important}.flex-xl-order-2{order:2 !important}.flex-xl-order-none{order:inherit !important}}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:-webkit-sticky !important;position:sticky !important}@media (min-width: 544px){.position-sm-static{position:static !important}.position-sm-relative{position:relative !important}.position-sm-absolute{position:absolute !important}.position-sm-fixed{position:fixed !important}.position-sm-sticky{position:-webkit-sticky !important;position:sticky !important}}@media (min-width: 768px){.position-md-static{position:static !important}.position-md-relative{position:relative !important}.position-md-absolute{position:absolute !important}.position-md-fixed{position:fixed !important}.position-md-sticky{position:-webkit-sticky !important;position:sticky !important}}@media (min-width: 1012px){.position-lg-static{position:static !important}.position-lg-relative{position:relative !important}.position-lg-absolute{position:absolute !important}.position-lg-fixed{position:fixed !important}.position-lg-sticky{position:-webkit-sticky !important;position:sticky !important}}@media (min-width: 1280px){.position-xl-static{position:static !important}.position-xl-relative{position:relative !important}.position-xl-absolute{position:absolute !important}.position-xl-fixed{position:fixed !important}.position-xl-sticky{position:-webkit-sticky !important;position:sticky !important}}.top-0{top:0 !important}.right-0{right:0 !important}.bottom-0{bottom:0 !important}.left-0{left:0 !important}.v-align-middle{vertical-align:middle !important}.v-align-top{vertical-align:top !important}.v-align-bottom{vertical-align:bottom !important}.v-align-text-top{vertical-align:text-top !important}.v-align-text-bottom{vertical-align:text-bottom !important}.v-align-baseline{vertical-align:baseline !important}.overflow-visible{overflow:visible !important}.overflow-x-visible{overflow-x:visible !important}.overflow-y-visible{overflow-y:visible !important}.overflow-hidden{overflow:hidden !important}.overflow-x-hidden{overflow-x:hidden !important}.overflow-y-hidden{overflow-y:hidden !important}.overflow-auto{overflow:auto !important}.overflow-x-auto{overflow-x:auto !important}.overflow-y-auto{overflow-y:auto !important}.overflow-scroll{overflow:scroll !important}.overflow-x-scroll{overflow-x:scroll !important}.overflow-y-scroll{overflow-y:scroll !important}.clearfix::before{display:table;content:\"\"}.clearfix::after{display:table;clear:both;content:\"\"}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}@media (min-width: 544px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}}@media (min-width: 1012px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}}@media (min-width: 1280px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}}.width-fit{max-width:100% !important}.width-full{width:100% !important}.height-fit{max-height:100% !important}.height-full{height:100% !important}.min-width-0{min-width:0 !important}.width-auto{width:auto !important}.direction-rtl{direction:rtl !important}.direction-ltr{direction:ltr !important}@media (min-width: 544px){.width-sm-auto{width:auto !important}.direction-sm-rtl{direction:rtl !important}.direction-sm-ltr{direction:ltr !important}}@media (min-width: 768px){.width-md-auto{width:auto !important}.direction-md-rtl{direction:rtl !important}.direction-md-ltr{direction:ltr !important}}@media (min-width: 1012px){.width-lg-auto{width:auto !important}.direction-lg-rtl{direction:rtl !important}.direction-lg-ltr{direction:ltr !important}}@media (min-width: 1280px){.width-xl-auto{width:auto !important}.direction-xl-rtl{direction:rtl !important}.direction-xl-ltr{direction:ltr !important}}.m-0{margin:0 !important}.mt-0{margin-top:0 !important}.mr-0{margin-right:0 !important}.mb-0{margin-bottom:0 !important}.ml-0{margin-left:0 !important}.mx-0{margin-right:0 !important;margin-left:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.m-1{margin:4px !important}.mt-1{margin-top:4px !important}.mr-1{margin-right:4px !important}.mb-1{margin-bottom:4px !important}.ml-1{margin-left:4px !important}.mt-n1{margin-top:-4px !important}.mr-n1{margin-right:-4px !important}.mb-n1{margin-bottom:-4px !important}.ml-n1{margin-left:-4px !important}.mx-1{margin-right:4px !important;margin-left:4px !important}.my-1{margin-top:4px !important;margin-bottom:4px !important}.m-2{margin:8px !important}.mt-2{margin-top:8px !important}.mr-2{margin-right:8px !important}.mb-2{margin-bottom:8px !important}.ml-2{margin-left:8px !important}.mt-n2{margin-top:-8px !important}.mr-n2{margin-right:-8px !important}.mb-n2{margin-bottom:-8px !important}.ml-n2{margin-left:-8px !important}.mx-2{margin-right:8px !important;margin-left:8px !important}.my-2{margin-top:8px !important;margin-bottom:8px !important}.m-3{margin:16px !important}.mt-3{margin-top:16px !important}.mr-3{margin-right:16px !important}.mb-3{margin-bottom:16px !important}.ml-3{margin-left:16px !important}.mt-n3{margin-top:-16px !important}.mr-n3{margin-right:-16px !important}.mb-n3{margin-bottom:-16px !important}.ml-n3{margin-left:-16px !important}.mx-3{margin-right:16px !important;margin-left:16px !important}.my-3{margin-top:16px !important;margin-bottom:16px !important}.m-4{margin:24px !important}.mt-4{margin-top:24px !important}.mr-4{margin-right:24px !important}.mb-4{margin-bottom:24px !important}.ml-4{margin-left:24px !important}.mt-n4{margin-top:-24px !important}.mr-n4{margin-right:-24px !important}.mb-n4{margin-bottom:-24px !important}.ml-n4{margin-left:-24px !important}.mx-4{margin-right:24px !important;margin-left:24px !important}.my-4{margin-top:24px !important;margin-bottom:24px !important}.m-5{margin:32px !important}.mt-5{margin-top:32px !important}.mr-5{margin-right:32px !important}.mb-5{margin-bottom:32px !important}.ml-5{margin-left:32px !important}.mt-n5{margin-top:-32px !important}.mr-n5{margin-right:-32px !important}.mb-n5{margin-bottom:-32px !important}.ml-n5{margin-left:-32px !important}.mx-5{margin-right:32px !important;margin-left:32px !important}.my-5{margin-top:32px !important;margin-bottom:32px !important}.m-6{margin:40px !important}.mt-6{margin-top:40px !important}.mr-6{margin-right:40px !important}.mb-6{margin-bottom:40px !important}.ml-6{margin-left:40px !important}.mt-n6{margin-top:-40px !important}.mr-n6{margin-right:-40px !important}.mb-n6{margin-bottom:-40px !important}.ml-n6{margin-left:-40px !important}.mx-6{margin-right:40px !important;margin-left:40px !important}.my-6{margin-top:40px !important;margin-bottom:40px !important}.mx-auto{margin-right:auto !important;margin-left:auto !important}@media (min-width: 544px){.m-sm-0{margin:0 !important}.mt-sm-0{margin-top:0 !important}.mr-sm-0{margin-right:0 !important}.mb-sm-0{margin-bottom:0 !important}.ml-sm-0{margin-left:0 !important}.mx-sm-0{margin-right:0 !important;margin-left:0 !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.m-sm-1{margin:4px !important}.mt-sm-1{margin-top:4px !important}.mr-sm-1{margin-right:4px !important}.mb-sm-1{margin-bottom:4px !important}.ml-sm-1{margin-left:4px !important}.mt-sm-n1{margin-top:-4px !important}.mr-sm-n1{margin-right:-4px !important}.mb-sm-n1{margin-bottom:-4px !important}.ml-sm-n1{margin-left:-4px !important}.mx-sm-1{margin-right:4px !important;margin-left:4px !important}.my-sm-1{margin-top:4px !important;margin-bottom:4px !important}.m-sm-2{margin:8px !important}.mt-sm-2{margin-top:8px !important}.mr-sm-2{margin-right:8px !important}.mb-sm-2{margin-bottom:8px !important}.ml-sm-2{margin-left:8px !important}.mt-sm-n2{margin-top:-8px !important}.mr-sm-n2{margin-right:-8px !important}.mb-sm-n2{margin-bottom:-8px !important}.ml-sm-n2{margin-left:-8px !important}.mx-sm-2{margin-right:8px !important;margin-left:8px !important}.my-sm-2{margin-top:8px !important;margin-bottom:8px !important}.m-sm-3{margin:16px !important}.mt-sm-3{margin-top:16px !important}.mr-sm-3{margin-right:16px !important}.mb-sm-3{margin-bottom:16px !important}.ml-sm-3{margin-left:16px !important}.mt-sm-n3{margin-top:-16px !important}.mr-sm-n3{margin-right:-16px !important}.mb-sm-n3{margin-bottom:-16px !important}.ml-sm-n3{margin-left:-16px !important}.mx-sm-3{margin-right:16px !important;margin-left:16px !important}.my-sm-3{margin-top:16px !important;margin-bottom:16px !important}.m-sm-4{margin:24px !important}.mt-sm-4{margin-top:24px !important}.mr-sm-4{margin-right:24px !important}.mb-sm-4{margin-bottom:24px !important}.ml-sm-4{margin-left:24px !important}.mt-sm-n4{margin-top:-24px !important}.mr-sm-n4{margin-right:-24px !important}.mb-sm-n4{margin-bottom:-24px !important}.ml-sm-n4{margin-left:-24px !important}.mx-sm-4{margin-right:24px !important;margin-left:24px !important}.my-sm-4{margin-top:24px !important;margin-bottom:24px !important}.m-sm-5{margin:32px !important}.mt-sm-5{margin-top:32px !important}.mr-sm-5{margin-right:32px !important}.mb-sm-5{margin-bottom:32px !important}.ml-sm-5{margin-left:32px !important}.mt-sm-n5{margin-top:-32px !important}.mr-sm-n5{margin-right:-32px !important}.mb-sm-n5{margin-bottom:-32px !important}.ml-sm-n5{margin-left:-32px !important}.mx-sm-5{margin-right:32px !important;margin-left:32px !important}.my-sm-5{margin-top:32px !important;margin-bottom:32px !important}.m-sm-6{margin:40px !important}.mt-sm-6{margin-top:40px !important}.mr-sm-6{margin-right:40px !important}.mb-sm-6{margin-bottom:40px !important}.ml-sm-6{margin-left:40px !important}.mt-sm-n6{margin-top:-40px !important}.mr-sm-n6{margin-right:-40px !important}.mb-sm-n6{margin-bottom:-40px !important}.ml-sm-n6{margin-left:-40px !important}.mx-sm-6{margin-right:40px !important;margin-left:40px !important}.my-sm-6{margin-top:40px !important;margin-bottom:40px !important}.mx-sm-auto{margin-right:auto !important;margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0{margin-top:0 !important}.mr-md-0{margin-right:0 !important}.mb-md-0{margin-bottom:0 !important}.ml-md-0{margin-left:0 !important}.mx-md-0{margin-right:0 !important;margin-left:0 !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.m-md-1{margin:4px !important}.mt-md-1{margin-top:4px !important}.mr-md-1{margin-right:4px !important}.mb-md-1{margin-bottom:4px !important}.ml-md-1{margin-left:4px !important}.mt-md-n1{margin-top:-4px !important}.mr-md-n1{margin-right:-4px !important}.mb-md-n1{margin-bottom:-4px !important}.ml-md-n1{margin-left:-4px !important}.mx-md-1{margin-right:4px !important;margin-left:4px !important}.my-md-1{margin-top:4px !important;margin-bottom:4px !important}.m-md-2{margin:8px !important}.mt-md-2{margin-top:8px !important}.mr-md-2{margin-right:8px !important}.mb-md-2{margin-bottom:8px !important}.ml-md-2{margin-left:8px !important}.mt-md-n2{margin-top:-8px !important}.mr-md-n2{margin-right:-8px !important}.mb-md-n2{margin-bottom:-8px !important}.ml-md-n2{margin-left:-8px !important}.mx-md-2{margin-right:8px !important;margin-left:8px !important}.my-md-2{margin-top:8px !important;margin-bottom:8px !important}.m-md-3{margin:16px !important}.mt-md-3{margin-top:16px !important}.mr-md-3{margin-right:16px !important}.mb-md-3{margin-bottom:16px !important}.ml-md-3{margin-left:16px !important}.mt-md-n3{margin-top:-16px !important}.mr-md-n3{margin-right:-16px !important}.mb-md-n3{margin-bottom:-16px !important}.ml-md-n3{margin-left:-16px !important}.mx-md-3{margin-right:16px !important;margin-left:16px !important}.my-md-3{margin-top:16px !important;margin-bottom:16px !important}.m-md-4{margin:24px !important}.mt-md-4{margin-top:24px !important}.mr-md-4{margin-right:24px !important}.mb-md-4{margin-bottom:24px !important}.ml-md-4{margin-left:24px !important}.mt-md-n4{margin-top:-24px !important}.mr-md-n4{margin-right:-24px !important}.mb-md-n4{margin-bottom:-24px !important}.ml-md-n4{margin-left:-24px !important}.mx-md-4{margin-right:24px !important;margin-left:24px !important}.my-md-4{margin-top:24px !important;margin-bottom:24px !important}.m-md-5{margin:32px !important}.mt-md-5{margin-top:32px !important}.mr-md-5{margin-right:32px !important}.mb-md-5{margin-bottom:32px !important}.ml-md-5{margin-left:32px !important}.mt-md-n5{margin-top:-32px !important}.mr-md-n5{margin-right:-32px !important}.mb-md-n5{margin-bottom:-32px !important}.ml-md-n5{margin-left:-32px !important}.mx-md-5{margin-right:32px !important;margin-left:32px !important}.my-md-5{margin-top:32px !important;margin-bottom:32px !important}.m-md-6{margin:40px !important}.mt-md-6{margin-top:40px !important}.mr-md-6{margin-right:40px !important}.mb-md-6{margin-bottom:40px !important}.ml-md-6{margin-left:40px !important}.mt-md-n6{margin-top:-40px !important}.mr-md-n6{margin-right:-40px !important}.mb-md-n6{margin-bottom:-40px !important}.ml-md-n6{margin-left:-40px !important}.mx-md-6{margin-right:40px !important;margin-left:40px !important}.my-md-6{margin-top:40px !important;margin-bottom:40px !important}.mx-md-auto{margin-right:auto !important;margin-left:auto !important}}@media (min-width: 1012px){.m-lg-0{margin:0 !important}.mt-lg-0{margin-top:0 !important}.mr-lg-0{margin-right:0 !important}.mb-lg-0{margin-bottom:0 !important}.ml-lg-0{margin-left:0 !important}.mx-lg-0{margin-right:0 !important;margin-left:0 !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.m-lg-1{margin:4px !important}.mt-lg-1{margin-top:4px !important}.mr-lg-1{margin-right:4px !important}.mb-lg-1{margin-bottom:4px !important}.ml-lg-1{margin-left:4px !important}.mt-lg-n1{margin-top:-4px !important}.mr-lg-n1{margin-right:-4px !important}.mb-lg-n1{margin-bottom:-4px !important}.ml-lg-n1{margin-left:-4px !important}.mx-lg-1{margin-right:4px !important;margin-left:4px !important}.my-lg-1{margin-top:4px !important;margin-bottom:4px !important}.m-lg-2{margin:8px !important}.mt-lg-2{margin-top:8px !important}.mr-lg-2{margin-right:8px !important}.mb-lg-2{margin-bottom:8px !important}.ml-lg-2{margin-left:8px !important}.mt-lg-n2{margin-top:-8px !important}.mr-lg-n2{margin-right:-8px !important}.mb-lg-n2{margin-bottom:-8px !important}.ml-lg-n2{margin-left:-8px !important}.mx-lg-2{margin-right:8px !important;margin-left:8px !important}.my-lg-2{margin-top:8px !important;margin-bottom:8px !important}.m-lg-3{margin:16px !important}.mt-lg-3{margin-top:16px !important}.mr-lg-3{margin-right:16px !important}.mb-lg-3{margin-bottom:16px !important}.ml-lg-3{margin-left:16px !important}.mt-lg-n3{margin-top:-16px !important}.mr-lg-n3{margin-right:-16px !important}.mb-lg-n3{margin-bottom:-16px !important}.ml-lg-n3{margin-left:-16px !important}.mx-lg-3{margin-right:16px !important;margin-left:16px !important}.my-lg-3{margin-top:16px !important;margin-bottom:16px !important}.m-lg-4{margin:24px !important}.mt-lg-4{margin-top:24px !important}.mr-lg-4{margin-right:24px !important}.mb-lg-4{margin-bottom:24px !important}.ml-lg-4{margin-left:24px !important}.mt-lg-n4{margin-top:-24px !important}.mr-lg-n4{margin-right:-24px !important}.mb-lg-n4{margin-bottom:-24px !important}.ml-lg-n4{margin-left:-24px !important}.mx-lg-4{margin-right:24px !important;margin-left:24px !important}.my-lg-4{margin-top:24px !important;margin-bottom:24px !important}.m-lg-5{margin:32px !important}.mt-lg-5{margin-top:32px !important}.mr-lg-5{margin-right:32px !important}.mb-lg-5{margin-bottom:32px !important}.ml-lg-5{margin-left:32px !important}.mt-lg-n5{margin-top:-32px !important}.mr-lg-n5{margin-right:-32px !important}.mb-lg-n5{margin-bottom:-32px !important}.ml-lg-n5{margin-left:-32px !important}.mx-lg-5{margin-right:32px !important;margin-left:32px !important}.my-lg-5{margin-top:32px !important;margin-bottom:32px !important}.m-lg-6{margin:40px !important}.mt-lg-6{margin-top:40px !important}.mr-lg-6{margin-right:40px !important}.mb-lg-6{margin-bottom:40px !important}.ml-lg-6{margin-left:40px !important}.mt-lg-n6{margin-top:-40px !important}.mr-lg-n6{margin-right:-40px !important}.mb-lg-n6{margin-bottom:-40px !important}.ml-lg-n6{margin-left:-40px !important}.mx-lg-6{margin-right:40px !important;margin-left:40px !important}.my-lg-6{margin-top:40px !important;margin-bottom:40px !important}.mx-lg-auto{margin-right:auto !important;margin-left:auto !important}}@media (min-width: 1280px){.m-xl-0{margin:0 !important}.mt-xl-0{margin-top:0 !important}.mr-xl-0{margin-right:0 !important}.mb-xl-0{margin-bottom:0 !important}.ml-xl-0{margin-left:0 !important}.mx-xl-0{margin-right:0 !important;margin-left:0 !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.m-xl-1{margin:4px !important}.mt-xl-1{margin-top:4px !important}.mr-xl-1{margin-right:4px !important}.mb-xl-1{margin-bottom:4px !important}.ml-xl-1{margin-left:4px !important}.mt-xl-n1{margin-top:-4px !important}.mr-xl-n1{margin-right:-4px !important}.mb-xl-n1{margin-bottom:-4px !important}.ml-xl-n1{margin-left:-4px !important}.mx-xl-1{margin-right:4px !important;margin-left:4px !important}.my-xl-1{margin-top:4px !important;margin-bottom:4px !important}.m-xl-2{margin:8px !important}.mt-xl-2{margin-top:8px !important}.mr-xl-2{margin-right:8px !important}.mb-xl-2{margin-bottom:8px !important}.ml-xl-2{margin-left:8px !important}.mt-xl-n2{margin-top:-8px !important}.mr-xl-n2{margin-right:-8px !important}.mb-xl-n2{margin-bottom:-8px !important}.ml-xl-n2{margin-left:-8px !important}.mx-xl-2{margin-right:8px !important;margin-left:8px !important}.my-xl-2{margin-top:8px !important;margin-bottom:8px !important}.m-xl-3{margin:16px !important}.mt-xl-3{margin-top:16px !important}.mr-xl-3{margin-right:16px !important}.mb-xl-3{margin-bottom:16px !important}.ml-xl-3{margin-left:16px !important}.mt-xl-n3{margin-top:-16px !important}.mr-xl-n3{margin-right:-16px !important}.mb-xl-n3{margin-bottom:-16px !important}.ml-xl-n3{margin-left:-16px !important}.mx-xl-3{margin-right:16px !important;margin-left:16px !important}.my-xl-3{margin-top:16px !important;margin-bottom:16px !important}.m-xl-4{margin:24px !important}.mt-xl-4{margin-top:24px !important}.mr-xl-4{margin-right:24px !important}.mb-xl-4{margin-bottom:24px !important}.ml-xl-4{margin-left:24px !important}.mt-xl-n4{margin-top:-24px !important}.mr-xl-n4{margin-right:-24px !important}.mb-xl-n4{margin-bottom:-24px !important}.ml-xl-n4{margin-left:-24px !important}.mx-xl-4{margin-right:24px !important;margin-left:24px !important}.my-xl-4{margin-top:24px !important;margin-bottom:24px !important}.m-xl-5{margin:32px !important}.mt-xl-5{margin-top:32px !important}.mr-xl-5{margin-right:32px !important}.mb-xl-5{margin-bottom:32px !important}.ml-xl-5{margin-left:32px !important}.mt-xl-n5{margin-top:-32px !important}.mr-xl-n5{margin-right:-32px !important}.mb-xl-n5{margin-bottom:-32px !important}.ml-xl-n5{margin-left:-32px !important}.mx-xl-5{margin-right:32px !important;margin-left:32px !important}.my-xl-5{margin-top:32px !important;margin-bottom:32px !important}.m-xl-6{margin:40px !important}.mt-xl-6{margin-top:40px !important}.mr-xl-6{margin-right:40px !important}.mb-xl-6{margin-bottom:40px !important}.ml-xl-6{margin-left:40px !important}.mt-xl-n6{margin-top:-40px !important}.mr-xl-n6{margin-right:-40px !important}.mb-xl-n6{margin-bottom:-40px !important}.ml-xl-n6{margin-left:-40px !important}.mx-xl-6{margin-right:40px !important;margin-left:40px !important}.my-xl-6{margin-top:40px !important;margin-bottom:40px !important}.mx-xl-auto{margin-right:auto !important;margin-left:auto !important}}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.px-0{padding-right:0 !important;padding-left:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:4px !important}.pt-1{padding-top:4px !important}.pr-1{padding-right:4px !important}.pb-1{padding-bottom:4px !important}.pl-1{padding-left:4px !important}.px-1{padding-right:4px !important;padding-left:4px !important}.py-1{padding-top:4px !important;padding-bottom:4px !important}.p-2{padding:8px !important}.pt-2{padding-top:8px !important}.pr-2{padding-right:8px !important}.pb-2{padding-bottom:8px !important}.pl-2{padding-left:8px !important}.px-2{padding-right:8px !important;padding-left:8px !important}.py-2{padding-top:8px !important;padding-bottom:8px !important}.p-3{padding:16px !important}.pt-3{padding-top:16px !important}.pr-3{padding-right:16px !important}.pb-3{padding-bottom:16px !important}.pl-3{padding-left:16px !important}.px-3{padding-right:16px !important;padding-left:16px !important}.py-3{padding-top:16px !important;padding-bottom:16px !important}.p-4{padding:24px !important}.pt-4{padding-top:24px !important}.pr-4{padding-right:24px !important}.pb-4{padding-bottom:24px !important}.pl-4{padding-left:24px !important}.px-4{padding-right:24px !important;padding-left:24px !important}.py-4{padding-top:24px !important;padding-bottom:24px !important}.p-5{padding:32px !important}.pt-5{padding-top:32px !important}.pr-5{padding-right:32px !important}.pb-5{padding-bottom:32px !important}.pl-5{padding-left:32px !important}.px-5{padding-right:32px !important;padding-left:32px !important}.py-5{padding-top:32px !important;padding-bottom:32px !important}.p-6{padding:40px !important}.pt-6{padding-top:40px !important}.pr-6{padding-right:40px !important}.pb-6{padding-bottom:40px !important}.pl-6{padding-left:40px !important}.px-6{padding-right:40px !important;padding-left:40px !important}.py-6{padding-top:40px !important;padding-bottom:40px !important}@media (min-width: 544px){.p-sm-0{padding:0 !important}.pt-sm-0{padding-top:0 !important}.pr-sm-0{padding-right:0 !important}.pb-sm-0{padding-bottom:0 !important}.pl-sm-0{padding-left:0 !important}.px-sm-0{padding-right:0 !important;padding-left:0 !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.p-sm-1{padding:4px !important}.pt-sm-1{padding-top:4px !important}.pr-sm-1{padding-right:4px !important}.pb-sm-1{padding-bottom:4px !important}.pl-sm-1{padding-left:4px !important}.px-sm-1{padding-right:4px !important;padding-left:4px !important}.py-sm-1{padding-top:4px !important;padding-bottom:4px !important}.p-sm-2{padding:8px !important}.pt-sm-2{padding-top:8px !important}.pr-sm-2{padding-right:8px !important}.pb-sm-2{padding-bottom:8px !important}.pl-sm-2{padding-left:8px !important}.px-sm-2{padding-right:8px !important;padding-left:8px !important}.py-sm-2{padding-top:8px !important;padding-bottom:8px !important}.p-sm-3{padding:16px !important}.pt-sm-3{padding-top:16px !important}.pr-sm-3{padding-right:16px !important}.pb-sm-3{padding-bottom:16px !important}.pl-sm-3{padding-left:16px !important}.px-sm-3{padding-right:16px !important;padding-left:16px !important}.py-sm-3{padding-top:16px !important;padding-bottom:16px !important}.p-sm-4{padding:24px !important}.pt-sm-4{padding-top:24px !important}.pr-sm-4{padding-right:24px !important}.pb-sm-4{padding-bottom:24px !important}.pl-sm-4{padding-left:24px !important}.px-sm-4{padding-right:24px !important;padding-left:24px !important}.py-sm-4{padding-top:24px !important;padding-bottom:24px !important}.p-sm-5{padding:32px !important}.pt-sm-5{padding-top:32px !important}.pr-sm-5{padding-right:32px !important}.pb-sm-5{padding-bottom:32px !important}.pl-sm-5{padding-left:32px !important}.px-sm-5{padding-right:32px !important;padding-left:32px !important}.py-sm-5{padding-top:32px !important;padding-bottom:32px !important}.p-sm-6{padding:40px !important}.pt-sm-6{padding-top:40px !important}.pr-sm-6{padding-right:40px !important}.pb-sm-6{padding-bottom:40px !important}.pl-sm-6{padding-left:40px !important}.px-sm-6{padding-right:40px !important;padding-left:40px !important}.py-sm-6{padding-top:40px !important;padding-bottom:40px !important}}@media (min-width: 768px){.p-md-0{padding:0 !important}.pt-md-0{padding-top:0 !important}.pr-md-0{padding-right:0 !important}.pb-md-0{padding-bottom:0 !important}.pl-md-0{padding-left:0 !important}.px-md-0{padding-right:0 !important;padding-left:0 !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.p-md-1{padding:4px !important}.pt-md-1{padding-top:4px !important}.pr-md-1{padding-right:4px !important}.pb-md-1{padding-bottom:4px !important}.pl-md-1{padding-left:4px !important}.px-md-1{padding-right:4px !important;padding-left:4px !important}.py-md-1{padding-top:4px !important;padding-bottom:4px !important}.p-md-2{padding:8px !important}.pt-md-2{padding-top:8px !important}.pr-md-2{padding-right:8px !important}.pb-md-2{padding-bottom:8px !important}.pl-md-2{padding-left:8px !important}.px-md-2{padding-right:8px !important;padding-left:8px !important}.py-md-2{padding-top:8px !important;padding-bottom:8px !important}.p-md-3{padding:16px !important}.pt-md-3{padding-top:16px !important}.pr-md-3{padding-right:16px !important}.pb-md-3{padding-bottom:16px !important}.pl-md-3{padding-left:16px !important}.px-md-3{padding-right:16px !important;padding-left:16px !important}.py-md-3{padding-top:16px !important;padding-bottom:16px !important}.p-md-4{padding:24px !important}.pt-md-4{padding-top:24px !important}.pr-md-4{padding-right:24px !important}.pb-md-4{padding-bottom:24px !important}.pl-md-4{padding-left:24px !important}.px-md-4{padding-right:24px !important;padding-left:24px !important}.py-md-4{padding-top:24px !important;padding-bottom:24px !important}.p-md-5{padding:32px !important}.pt-md-5{padding-top:32px !important}.pr-md-5{padding-right:32px !important}.pb-md-5{padding-bottom:32px !important}.pl-md-5{padding-left:32px !important}.px-md-5{padding-right:32px !important;padding-left:32px !important}.py-md-5{padding-top:32px !important;padding-bottom:32px !important}.p-md-6{padding:40px !important}.pt-md-6{padding-top:40px !important}.pr-md-6{padding-right:40px !important}.pb-md-6{padding-bottom:40px !important}.pl-md-6{padding-left:40px !important}.px-md-6{padding-right:40px !important;padding-left:40px !important}.py-md-6{padding-top:40px !important;padding-bottom:40px !important}}@media (min-width: 1012px){.p-lg-0{padding:0 !important}.pt-lg-0{padding-top:0 !important}.pr-lg-0{padding-right:0 !important}.pb-lg-0{padding-bottom:0 !important}.pl-lg-0{padding-left:0 !important}.px-lg-0{padding-right:0 !important;padding-left:0 !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.p-lg-1{padding:4px !important}.pt-lg-1{padding-top:4px !important}.pr-lg-1{padding-right:4px !important}.pb-lg-1{padding-bottom:4px !important}.pl-lg-1{padding-left:4px !important}.px-lg-1{padding-right:4px !important;padding-left:4px !important}.py-lg-1{padding-top:4px !important;padding-bottom:4px !important}.p-lg-2{padding:8px !important}.pt-lg-2{padding-top:8px !important}.pr-lg-2{padding-right:8px !important}.pb-lg-2{padding-bottom:8px !important}.pl-lg-2{padding-left:8px !important}.px-lg-2{padding-right:8px !important;padding-left:8px !important}.py-lg-2{padding-top:8px !important;padding-bottom:8px !important}.p-lg-3{padding:16px !important}.pt-lg-3{padding-top:16px !important}.pr-lg-3{padding-right:16px !important}.pb-lg-3{padding-bottom:16px !important}.pl-lg-3{padding-left:16px !important}.px-lg-3{padding-right:16px !important;padding-left:16px !important}.py-lg-3{padding-top:16px !important;padding-bottom:16px !important}.p-lg-4{padding:24px !important}.pt-lg-4{padding-top:24px !important}.pr-lg-4{padding-right:24px !important}.pb-lg-4{padding-bottom:24px !important}.pl-lg-4{padding-left:24px !important}.px-lg-4{padding-right:24px !important;padding-left:24px !important}.py-lg-4{padding-top:24px !important;padding-bottom:24px !important}.p-lg-5{padding:32px !important}.pt-lg-5{padding-top:32px !important}.pr-lg-5{padding-right:32px !important}.pb-lg-5{padding-bottom:32px !important}.pl-lg-5{padding-left:32px !important}.px-lg-5{padding-right:32px !important;padding-left:32px !important}.py-lg-5{padding-top:32px !important;padding-bottom:32px !important}.p-lg-6{padding:40px !important}.pt-lg-6{padding-top:40px !important}.pr-lg-6{padding-right:40px !important}.pb-lg-6{padding-bottom:40px !important}.pl-lg-6{padding-left:40px !important}.px-lg-6{padding-right:40px !important;padding-left:40px !important}.py-lg-6{padding-top:40px !important;padding-bottom:40px !important}}@media (min-width: 1280px){.p-xl-0{padding:0 !important}.pt-xl-0{padding-top:0 !important}.pr-xl-0{padding-right:0 !important}.pb-xl-0{padding-bottom:0 !important}.pl-xl-0{padding-left:0 !important}.px-xl-0{padding-right:0 !important;padding-left:0 !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.p-xl-1{padding:4px !important}.pt-xl-1{padding-top:4px !important}.pr-xl-1{padding-right:4px !important}.pb-xl-1{padding-bottom:4px !important}.pl-xl-1{padding-left:4px !important}.px-xl-1{padding-right:4px !important;padding-left:4px !important}.py-xl-1{padding-top:4px !important;padding-bottom:4px !important}.p-xl-2{padding:8px !important}.pt-xl-2{padding-top:8px !important}.pr-xl-2{padding-right:8px !important}.pb-xl-2{padding-bottom:8px !important}.pl-xl-2{padding-left:8px !important}.px-xl-2{padding-right:8px !important;padding-left:8px !important}.py-xl-2{padding-top:8px !important;padding-bottom:8px !important}.p-xl-3{padding:16px !important}.pt-xl-3{padding-top:16px !important}.pr-xl-3{padding-right:16px !important}.pb-xl-3{padding-bottom:16px !important}.pl-xl-3{padding-left:16px !important}.px-xl-3{padding-right:16px !important;padding-left:16px !important}.py-xl-3{padding-top:16px !important;padding-bottom:16px !important}.p-xl-4{padding:24px !important}.pt-xl-4{padding-top:24px !important}.pr-xl-4{padding-right:24px !important}.pb-xl-4{padding-bottom:24px !important}.pl-xl-4{padding-left:24px !important}.px-xl-4{padding-right:24px !important;padding-left:24px !important}.py-xl-4{padding-top:24px !important;padding-bottom:24px !important}.p-xl-5{padding:32px !important}.pt-xl-5{padding-top:32px !important}.pr-xl-5{padding-right:32px !important}.pb-xl-5{padding-bottom:32px !important}.pl-xl-5{padding-left:32px !important}.px-xl-5{padding-right:32px !important;padding-left:32px !important}.py-xl-5{padding-top:32px !important;padding-bottom:32px !important}.p-xl-6{padding:40px !important}.pt-xl-6{padding-top:40px !important}.pr-xl-6{padding-right:40px !important}.pb-xl-6{padding-bottom:40px !important}.pl-xl-6{padding-left:40px !important}.px-xl-6{padding-right:40px !important;padding-left:40px !important}.py-xl-6{padding-top:40px !important;padding-bottom:40px !important}}.p-responsive{padding-right:16px !important;padding-left:16px !important}@media (min-width: 544px){.p-responsive{padding-right:40px !important;padding-left:40px !important}}@media (min-width: 1012px){.p-responsive{padding-right:16px !important;padding-left:16px !important}}.h1{font-size:26px !important}@media (min-width: 768px){.h1{font-size:32px !important}}.h2{font-size:22px !important}@media (min-width: 768px){.h2{font-size:24px !important}}.h3{font-size:18px !important}@media (min-width: 768px){.h3{font-size:20px !important}}.h4{font-size:16px !important}.h5{font-size:14px !important}.h6{font-size:12px !important}.h1,.h2,.h3,.h4,.h5,.h6{font-weight:600 !important}.f1{font-size:26px !important}@media (min-width: 768px){.f1{font-size:32px !important}}.f2{font-size:22px !important}@media (min-width: 768px){.f2{font-size:24px !important}}.f3{font-size:18px !important}@media (min-width: 768px){.f3{font-size:20px !important}}.f4{font-size:16px !important}@media (min-width: 768px){.f4{font-size:16px !important}}.f5{font-size:14px !important}.f6{font-size:12px !important}.f00-light{font-size:40px !important;font-weight:300 !important}@media (min-width: 768px){.f00-light{font-size:48px !important}}.f0-light{font-size:32px !important;font-weight:300 !important}@media (min-width: 768px){.f0-light{font-size:40px !important}}.f1-light{font-size:26px !important;font-weight:300 !important}@media (min-width: 768px){.f1-light{font-size:32px !important}}.f2-light{font-size:22px !important;font-weight:300 !important}@media (min-width: 768px){.f2-light{font-size:24px !important}}.f3-light{font-size:18px !important;font-weight:300 !important}@media (min-width: 768px){.f3-light{font-size:20px !important}}.text-small{font-size:12px !important}.lead{margin-bottom:30px;font-size:20px;font-weight:300;color:#586069}.lh-condensed-ultra{line-height:1 !important}.lh-condensed{line-height:1.25 !important}.lh-default{line-height:1.5 !important}.lh-0{line-height:0 !important}@media (min-width: 544px){.lh-sm-condensed-ultra{line-height:1 !important}.lh-sm-condensed{line-height:1.25 !important}.lh-sm-default{line-height:1.5 !important}.lh-sm-0{line-height:0 !important}}@media (min-width: 768px){.lh-md-condensed-ultra{line-height:1 !important}.lh-md-condensed{line-height:1.25 !important}.lh-md-default{line-height:1.5 !important}.lh-md-0{line-height:0 !important}}@media (min-width: 1012px){.lh-lg-condensed-ultra{line-height:1 !important}.lh-lg-condensed{line-height:1.25 !important}.lh-lg-default{line-height:1.5 !important}.lh-lg-0{line-height:0 !important}}@media (min-width: 1280px){.lh-xl-condensed-ultra{line-height:1 !important}.lh-xl-condensed{line-height:1.25 !important}.lh-xl-default{line-height:1.5 !important}.lh-xl-0{line-height:0 !important}}.text-right{text-align:right !important}.text-left{text-align:left !important}.text-center{text-align:center !important}@media (min-width: 544px){.text-sm-right{text-align:right !important}.text-sm-left{text-align:left !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.text-md-right{text-align:right !important}.text-md-left{text-align:left !important}.text-md-center{text-align:center !important}}@media (min-width: 1012px){.text-lg-right{text-align:right !important}.text-lg-left{text-align:left !important}.text-lg-center{text-align:center !important}}@media (min-width: 1280px){.text-xl-right{text-align:right !important}.text-xl-left{text-align:left !important}.text-xl-center{text-align:center !important}}.text-normal{font-weight:400 !important}.text-bold{font-weight:600 !important}.text-italic{font-style:italic !important}.text-uppercase{text-transform:uppercase !important}.text-underline{text-decoration:underline !important}.no-underline{text-decoration:none !important}.no-wrap{white-space:nowrap !important}.ws-normal{white-space:normal !important}.break-word{word-break:break-word !important;word-wrap:break-word !important;overflow-wrap:break-word !important}.wb-break-all{word-break:break-all !important}.text-emphasized{font-weight:600;color:#24292e}.list-style-none{list-style:none !important}.text-shadow-dark{text-shadow:0 1px 1px rgba(27,31,35,0.25),0 1px 25px rgba(27,31,35,0.75)}.text-shadow-light{text-shadow:0 1px 0 rgba(255,255,255,0.5)}.text-mono{font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace !important}.user-select-none{-webkit-user-select:none !important;-moz-user-select:none !important;-ms-user-select:none !important;user-select:none !important}.d-block{display:block !important}.d-flex{display:flex !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-inline-flex{display:inline-flex !important}.d-none{display:none !important}.d-table{display:table !important}.d-table-cell{display:table-cell !important}@media (min-width: 544px){.d-sm-block{display:block !important}.d-sm-flex{display:flex !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-inline-flex{display:inline-flex !important}.d-sm-none{display:none !important}.d-sm-table{display:table !important}.d-sm-table-cell{display:table-cell !important}}@media (min-width: 768px){.d-md-block{display:block !important}.d-md-flex{display:flex !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-inline-flex{display:inline-flex !important}.d-md-none{display:none !important}.d-md-table{display:table !important}.d-md-table-cell{display:table-cell !important}}@media (min-width: 1012px){.d-lg-block{display:block !important}.d-lg-flex{display:flex !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-inline-flex{display:inline-flex !important}.d-lg-none{display:none !important}.d-lg-table{display:table !important}.d-lg-table-cell{display:table-cell !important}}@media (min-width: 1280px){.d-xl-block{display:block !important}.d-xl-flex{display:flex !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-inline-flex{display:inline-flex !important}.d-xl-none{display:none !important}.d-xl-table{display:table !important}.d-xl-table-cell{display:table-cell !important}}.v-hidden{visibility:hidden !important}.v-visible{visibility:visible !important}@media (max-width: 543px){.hide-sm{display:none !important}}@media (min-width: 544px) and (max-width: 767px){.hide-md{display:none !important}}@media (min-width: 768px) and (max-width: 1011px){.hide-lg{display:none !important}}@media (min-width: 1012px){.hide-xl{display:none !important}}.table-fixed{table-layout:fixed !important}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);word-wrap:normal;border:0}.show-on-focus{position:absolute;width:1px;height:1px;margin:0;overflow:hidden;clip:rect(1px, 1px, 1px, 1px)}.show-on-focus:focus{z-index:20;width:auto;height:auto;clip:auto}/*!\n * @primer/css/product\n * http://primer.style/css\n *\n * Released under MIT license. Copyright (c) 2019 GitHub Inc.\n */.flash{position:relative;padding:16px;color:#032f62;background-color:#dbedff;border:1px solid rgba(27,31,35,0.15);border-radius:3px}.flash p:last-child{margin-bottom:0}.flash-messages{margin-bottom:24px}.flash-close{float:right;padding:16px;margin:-16px;color:inherit;text-align:center;cursor:pointer;background:none;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0.6}.flash-close:hover{opacity:1}.flash-action{float:right;margin-top:-3px;margin-left:24px}.flash-warn{color:#735c0f;background-color:#fffbdd;border-color:rgba(27,31,35,0.15)}.flash-error{color:#86181d;background-color:#ffdce0;border-color:rgba(27,31,35,0.15)}.flash-success{color:#165c26;background-color:#dcffe4;border-color:rgba(27,31,35,0.15)}.flash-full{margin-top:-1px;border-width:1px 0;border-radius:0}.flash-banner{position:fixed;top:0;z-index:90;width:100%;border-top:0;border-right:0;border-left:0;border-radius:0}.warning{padding:.5em;margin-bottom:0.8em;font-weight:600;background-color:#fffbdd}.autocomplete-results{position:absolute;z-index:99;width:100%;max-height:20em;overflow-y:auto;font-size:13px;list-style:none;background:#fff;border-radius:3px;box-shadow:0 0 5px rgba(27,31,35,0.3)}.autocomplete-item{display:block;padding:4px 8px;overflow:hidden;font-weight:600;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.autocomplete-item:hover,.autocomplete-item.selected,.autocomplete-item[aria-selected=true],.autocomplete-item.navigation-focus{color:#fff;text-decoration:none;background-color:#0366d6}.autocomplete-item:hover *,.autocomplete-item.selected *,.autocomplete-item[aria-selected=true] *,.autocomplete-item.navigation-focus *{color:inherit !important}.suggester{position:relative;top:0;left:0;min-width:180px;padding:0;margin:0;margin-top:24px;list-style:none;cursor:pointer;background:#fff;border:1px #e1e4e8 solid;border-radius:3px;box-shadow:0 1px 5px rgba(27,31,35,0.15)}.suggester li{display:block;padding:4px 8px;font-weight:600;border-bottom:1px #e1e4e8 solid}.suggester li small{font-weight:400;color:#586069}.suggester li:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.suggester li:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.suggester li:hover,.suggester li[aria-selected=\"true\"],.suggester li.navigation-focus{color:#fff;text-decoration:none;background:#0366d6}.suggester li:hover small,.suggester li[aria-selected=\"true\"] small,.suggester li.navigation-focus small{color:#fff}.suggester-container{position:absolute;top:0;left:0;z-index:30}@media (max-width: 544px){.page-responsive .suggester-container{right:8px !important;left:8px !important}.page-responsive .suggester li{padding:8px 16px}}.avatar{display:inline-block;overflow:hidden;line-height:1;vertical-align:middle;border-radius:3px}.avatar-small{border-radius:2px}.avatar-link{float:left;line-height:1}.avatar-group-item{display:inline-block;margin-bottom:3px}.avatar-parent-child{position:relative}.avatar-child{position:absolute;right:-15%;bottom:-9%;background-color:#fff;border-radius:2px;box-shadow:-2px -2px 0 rgba(255,255,255,0.8)}.AvatarStack{position:relative;min-width:26px;height:20px}.AvatarStack .AvatarStack-body{position:absolute}.AvatarStack.AvatarStack--two{min-width:36px}.AvatarStack.AvatarStack--three-plus{min-width:46px}.AvatarStack-body{display:flex;background:#fff}.AvatarStack-body .avatar{position:relative;z-index:2;display:flex;width:20px;height:20px;box-sizing:content-box;margin-right:-11px;background-color:#fff;border-right:1px solid #fff;border-radius:2px;transition:margin 0.1s ease-in-out}.AvatarStack-body .avatar:first-child{z-index:3}.AvatarStack-body .avatar:last-child{z-index:1;border-right:0}.AvatarStack-body .avatar img{border-radius:2px}.AvatarStack-body .avatar:nth-child(n+4){display:none;opacity:0}.AvatarStack-body:hover .avatar{margin-right:3px}.AvatarStack-body:hover .avatar:nth-child(n+4){display:flex;opacity:1}.AvatarStack-body:hover .avatar-more{display:none !important}.avatar.avatar-more{z-index:1;margin-right:0;background:#f6f8fa}.avatar.avatar-more::before,.avatar.avatar-more::after{position:absolute;display:block;height:20px;content:\"\";border-radius:2px;outline:1px solid #fff}.avatar.avatar-more::before{width:17px;background:#e1e4e8}.avatar.avatar-more::after{width:14px;background:#d1d5da}.AvatarStack--right .AvatarStack-body{right:0;flex-direction:row-reverse}.AvatarStack--right .AvatarStack-body:hover .avatar{margin-right:0;margin-left:3px}.AvatarStack--right .avatar.avatar-more{background:#d1d5da}.AvatarStack--right .avatar.avatar-more::before{width:5px}.AvatarStack--right .avatar.avatar-more::after{width:2px;background:#f6f8fa}.AvatarStack--right .avatar{margin-right:0;margin-left:-11px;border-right:0;border-left:1px solid #fff}.CircleBadge{display:flex;align-items:center;justify-content:center;background-color:#fff;border-radius:50%;box-shadow:0 1px 5px rgba(27,31,35,0.15)}.CircleBadge-icon{max-width:60% !important;height:auto !important;max-height:55% !important}.CircleBadge--small{width:56px;height:56px}.CircleBadge--medium{width:96px;height:96px}.CircleBadge--large{width:128px;height:128px}.DashedConnection{position:relative}.DashedConnection::before{position:absolute;top:50%;left:0;width:100%;content:\"\";border-bottom:2px dashed #e1e4e8}.DashedConnection .CircleBadge{position:relative}.blankslate{position:relative;padding:32px;text-align:center}.blankslate code{padding:2px 5px 3px;font-size:14px;background:#fff;border:1px solid #eaecef;border-radius:3px}.blankslate img{width:56px;height:56px}.blankslate-icon{margin-right:4px;margin-bottom:8px;margin-left:4px;color:#a3aab1}.blankslate-capped{border-radius:0 0 3px 3px}.blankslate-spacious{padding:80px 40px}.blankslate-narrow{max-width:485px;margin:0 auto}.blankslate-large img{width:80px;height:80px}.blankslate-large h3{margin:16px 0;font-size:24px}.blankslate-large p{font-size:16px}.blankslate-clean-background{border:0}.branch-name{display:inline-block;padding:2px 6px;font:12px \"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;color:rgba(27,31,35,0.6);background-color:#eaf5ff;border-radius:3px}.branch-name .octicon{margin:1px -2px 0 0;color:#a8bbd0}a.branch-name{color:#0366d6}.dropdown{position:relative}.dropdown-caret{display:inline-block;width:0;height:0;vertical-align:middle;content:\"\";border-style:solid;border-width:4px 4px 0;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}.dropdown-menu{position:absolute;top:100%;left:0;z-index:100;width:160px;padding-top:4px;padding-bottom:4px;margin-top:2px;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(27,31,35,0.15);border-radius:4px;box-shadow:0 1px 15px rgba(27,31,35,0.15)}.dropdown-menu::before,.dropdown-menu::after{position:absolute;display:inline-block;content:\"\"}.dropdown-menu::before{border:8px solid transparent;border-bottom-color:rgba(27,31,35,0.15)}.dropdown-menu::after{border:7px solid transparent;border-bottom-color:#fff}.dropdown-menu>ul{list-style:none}.dropdown-menu-no-overflow{width:auto}.dropdown-menu-no-overflow .dropdown-item{padding:4px 16px;overflow:visible;text-overflow:inherit}.dropdown-item{display:block;padding:4px 8px 4px 16px;overflow:hidden;color:#24292e;text-overflow:ellipsis;white-space:nowrap}.dropdown-item:focus,.dropdown-item:hover{color:#fff;text-decoration:none;background-color:#0366d6;outline:none}.dropdown-item:focus>.octicon,.dropdown-item:hover>.octicon{color:inherit;opacity:1}.dropdown-item.btn-link{width:100%;text-align:left}.dropdown-signout{width:100%;text-align:left;background:none;border:0}.dropdown-divider{display:block;height:0;margin:8px 0;border-top:1px #e1e4e8 solid}.dropdown-header{padding:4px 16px;font-size:12px;color:#586069}.dropdown-item[aria-checked=\"false\"] .octicon-check{display:none}.dropdown-menu-w{top:0;right:100%;left:auto;width:auto;margin-top:0;margin-right:8px}.dropdown-menu-w::before{top:10px;right:-16px;left:auto;border-color:transparent;border-left-color:rgba(27,31,35,0.15)}.dropdown-menu-w::after{top:11px;right:-14px;left:auto;border-color:transparent;border-left-color:#fff}.dropdown-menu-e{top:0;left:100%;width:auto;margin-top:0;margin-left:8px}.dropdown-menu-e::before{top:8px;left:-16px;border-color:transparent;border-right-color:rgba(27,31,35,0.15)}.dropdown-menu-e::after{top:11px;left:-14px;border-color:transparent;border-right-color:#fff}.dropdown-menu-ne{top:auto;bottom:100%;left:0;margin-bottom:3px}.dropdown-menu-ne::before,.dropdown-menu-ne::after{top:auto;right:auto}.dropdown-menu-ne::before{bottom:-8px;left:9px;border-top:8px solid rgba(27,31,35,0.15);border-right:8px solid transparent;border-bottom:0;border-left:8px solid transparent}.dropdown-menu-ne::after{bottom:-7px;left:10px;border-top:7px solid #fff;border-right:7px solid transparent;border-bottom:0;border-left:7px solid transparent}.dropdown-menu-s{right:50%;left:auto;transform:translateX(50%)}.dropdown-menu-s::before{top:-16px;right:50%;transform:translateX(50%)}.dropdown-menu-s::after{top:-14px;right:50%;transform:translateX(50%)}.dropdown-menu-sw{right:0;left:auto}.dropdown-menu-sw::before{top:-16px;right:9px;left:auto}.dropdown-menu-sw::after{top:-14px;right:10px;left:auto}.dropdown-menu-se::before{top:-16px;left:9px}.dropdown-menu-se::after{top:-14px;left:10px}.dropdown-menu-dark{color:#fff;background:#2f363d;border-color:#444d56;box-shadow:0 1px 15px rgba(27,31,35,0.15)}.dropdown-menu-dark::before{border-bottom-color:#444d56}.dropdown-menu-dark::after{border-bottom-color:#2f363d}.dropdown-menu-dark .dropdown-header{color:#d1d5da}.dropdown-menu-dark .dropdown-divider{border-top-color:#444d56}.dropdown-menu-dark .dropdown-item{color:inherit}.dropdown-menu-dark.dropdown-menu-w::before{border-color:transparent transparent transparent #444d56}.dropdown-menu-dark.dropdown-menu-w::after{border-color:transparent transparent transparent #2f363d}.dropdown-menu-dark.dropdown-menu-e::before{border-color:transparent #444d56 transparent transparent}.dropdown-menu-dark.dropdown-menu-e::after{border-color:transparent #2f363d transparent transparent}.dropdown-menu-dark.dropdown-menu-ne::before{border-color:#444d56 transparent transparent transparent}.dropdown-menu-dark.dropdown-menu-ne::after{border-color:#2f363d transparent transparent transparent}.Header{z-index:32;display:flex;padding:16px;font-size:14px;line-height:1.5;color:rgba(255,255,255,0.7);background-color:#24292e;align-items:center;flex-wrap:nowrap}.Header-item{display:flex;margin-right:16px;align-self:stretch;align-items:center;flex-wrap:nowrap}.Header-item--full{flex:auto}.Header-link{font-weight:600;color:#fff;white-space:nowrap}.Header-link:hover,.Header-link:focus{color:rgba(255,255,255,0.7);text-decoration:none}.IssueLabel{height:20px;padding:0.15em 4px;font-size:12px;font-weight:600;line-height:15px;border-radius:2px;box-shadow:inset 0 -1px 0 rgba(27,31,35,0.12)}.IssueLabel .g-emoji{position:relative;top:-0.05em;display:inline-block;font-size:1em;line-height:1}.IssueLabel:hover{text-decoration:none}.IssueLabel--big{padding:4px 8px;font-size:14px;font-weight:600;border-radius:3px;transition:opacity 0.2s linear}.IssueLabel--big .g-emoji{display:inline-block;margin-top:-1px}.IssueLabel--big:hover{opacity:0.85}.labels{position:relative}.label,.Label{display:inline-block;padding:3px 4px;font-size:12px;font-weight:600;line-height:1;color:#fff;border-radius:2px;box-shadow:inset 0 -1px 0 rgba(27,31,35,0.12)}.label:hover,.Label:hover{text-decoration:none}.Label--gray{color:#586069;background-color:#eaecef}.Label--outline{margin-top:-1px;margin-bottom:-1px;font-weight:400;color:#586069;background-color:transparent;border:1px solid rgba(27,31,35,0.15);box-shadow:none}.Label--outline-green{color:#28a745;border:1px solid #34d058}.Label--gray-darker{background-color:#6a737d}.Label--orange{background-color:#d15704}.state,.State{display:inline-block;padding:4px 8px;font-weight:600;line-height:20px;color:#fff;text-align:center;white-space:nowrap;background-color:#6a737d;border-radius:3px}.State--green{background-color:#2cbe4e}.State--purple{background-color:#6f42c1}.State--red{background-color:#cb2431}.State--small{padding:.125em 4px;font-size:12px}.State--small .octicon{width:1em}.Counter{display:inline-block;padding:2px 5px;font-size:12px;font-weight:600;line-height:1;color:#586069;background-color:rgba(27,31,35,0.08);border-radius:20px}.Counter:empty{visibility:hidden}.Counter--gray-light{color:#24292e;background-color:rgba(27,31,35,0.15)}.Counter--gray{color:#fff;background-color:#6a737d}.diffstat{font-size:12px;font-weight:600;color:#586069;white-space:nowrap;cursor:default}.diffstat-block-deleted,.diffstat-block-added,.diffstat-block-neutral{display:inline-block;width:8px;height:8px;margin-left:1px}.diffstat-block-deleted{background-color:#cb2431}.diffstat-block-added{background-color:#2cbe4e}.diffstat-block-neutral{background-color:#d1d5da}.AnimatedEllipsis{display:inline-block;overflow:hidden;vertical-align:bottom}.AnimatedEllipsis::after{display:inline-block;content:\"...\";animation:AnimatedEllipsis-keyframes 1.2s steps(4, jump-none) infinite}@keyframes AnimatedEllipsis-keyframes{0%{transform:translateX(-100%)}}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\";font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px \"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #d1d5da;border-bottom-color:#d1d5da;border-radius:3px;box-shadow:inset 0 -1px 0 #d1d5da}.markdown-body::before{display:table;content:\"\"}.markdown-body::after{display:table;clear:both;content:\"\"}.markdown-body>*:first-child{margin-top:0 !important}.markdown-body>*:last-child{margin-bottom:0 !important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .absent{color:#cb2431}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:none}.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre,.markdown-body details{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:0.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1 tt,.markdown-body h1 code,.markdown-body h2 tt,.markdown-body h2 code,.markdown-body h3 tt,.markdown-body h3 code,.markdown-body h4 tt,.markdown-body h4 code,.markdown-body h5 tt,.markdown-body h5 code,.markdown-body h6 tt,.markdown-body h6 code{font-size:inherit}.markdown-body h1{padding-bottom:0.3em;font-size:2em;border-bottom:1px solid #eaecef}.markdown-body h2{padding-bottom:0.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:0.875em}.markdown-body h6{font-size:0.85em;color:#6a737d}.markdown-body ul,.markdown-body ol{padding-left:2em}.markdown-body ul.no-list,.markdown-body ol.no-list{padding:0;list-style-type:none}.markdown-body ul ul,.markdown-body ul ol,.markdown-body ol ol,.markdown-body ol ul{margin-top:0;margin-bottom:0}.markdown-body li{word-wrap:break-all}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table th,.markdown-body table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body table img{background-color:transparent}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{max-width:none;vertical-align:text-top;background-color:transparent}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{display:block;float:left;width:auto;padding:7px;margin:13px 0 0;overflow:hidden;border:1px solid #dfe2e5}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{display:block;padding:5px 0 0;clear:both;color:#24292e}.markdown-body span.align-center{display:block;overflow:hidden;clear:both}.markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown-body span.align-center span img{margin:0 auto;text-align:center}.markdown-body span.align-right{display:block;overflow:hidden;clear:both}.markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown-body span.align-right span img{margin:0;text-align:right}.markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown-body span.float-left span{margin:13px 0 0}.markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown-body code,.markdown-body tt{padding:0.2em 0.4em;margin:0;font-size:85%;background-color:rgba(27,31,35,0.05);border-radius:3px}.markdown-body code br,.markdown-body tt br{display:none}.markdown-body del code{text-decoration:inherit}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code,.markdown-body pre tt{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body .csv-data td,.markdown-body .csv-data th{padding:5px;overflow:hidden;font-size:12px;line-height:1;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-num{padding:10px 8px 9px;text-align:right;background:#fff;border:0}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{font-weight:600;background:#f6f8fa;border-top:0}.Popover{position:absolute;z-index:100}.Popover-message{position:relative;width:232px;margin-right:auto;margin-left:auto}.Popover-message::before,.Popover-message::after{position:absolute;left:50%;display:inline-block;content:\"\"}.Popover-message::before{top:-16px;margin-left:-9px;border:8px solid transparent;border-bottom-color:rgba(27,31,35,0.15)}.Popover-message::after{top:-14px;margin-left:-8px;border:7px solid transparent;border-bottom-color:#fff}.Popover-message--bottom::before,.Popover-message--bottom::after,.Popover-message--bottom-right::before,.Popover-message--bottom-right::after,.Popover-message--bottom-left::before,.Popover-message--bottom-left::after{top:auto;border-bottom-color:transparent}.Popover-message--bottom::before,.Popover-message--bottom-right::before,.Popover-message--bottom-left::before{bottom:-16px;border-top-color:rgba(27,31,35,0.15)}.Popover-message--bottom::after,.Popover-message--bottom-right::after,.Popover-message--bottom-left::after{bottom:-14px;border-top-color:#fff}.Popover-message--top-right,.Popover-message--bottom-right{right:-9px;margin-right:0}.Popover-message--top-right::before,.Popover-message--top-right::after,.Popover-message--bottom-right::before,.Popover-message--bottom-right::after{left:auto;margin-left:0}.Popover-message--top-right::before,.Popover-message--bottom-right::before{right:20px}.Popover-message--top-right::after,.Popover-message--bottom-right::after{right:21px}.Popover-message--top-left,.Popover-message--bottom-left{left:-9px;margin-left:0}.Popover-message--top-left::before,.Popover-message--top-left::after,.Popover-message--bottom-left::before,.Popover-message--bottom-left::after{left:24px;margin-left:0}.Popover-message--top-left::after,.Popover-message--bottom-left::after{left:25px}.Popover-message--right::before,.Popover-message--right::after,.Popover-message--right-top::before,.Popover-message--right-top::after,.Popover-message--right-bottom::before,.Popover-message--right-bottom::after,.Popover-message--left::before,.Popover-message--left::after,.Popover-message--left-top::before,.Popover-message--left-top::after,.Popover-message--left-bottom::before,.Popover-message--left-bottom::after{top:50%;left:auto;margin-left:0;border-bottom-color:transparent}.Popover-message--right::before,.Popover-message--right-top::before,.Popover-message--right-bottom::before,.Popover-message--left::before,.Popover-message--left-top::before,.Popover-message--left-bottom::before{margin-top:-9px}.Popover-message--right::after,.Popover-message--right-top::after,.Popover-message--right-bottom::after,.Popover-message--left::after,.Popover-message--left-top::after,.Popover-message--left-bottom::after{margin-top:-8px}.Popover-message--right::before,.Popover-message--right-top::before,.Popover-message--right-bottom::before{right:-16px;border-left-color:rgba(27,31,35,0.15)}.Popover-message--right::after,.Popover-message--right-top::after,.Popover-message--right-bottom::after{right:-14px;border-left-color:#fff}.Popover-message--left::before,.Popover-message--left-top::before,.Popover-message--left-bottom::before{left:-16px;border-right-color:rgba(27,31,35,0.15)}.Popover-message--left::after,.Popover-message--left-top::after,.Popover-message--left-bottom::after{left:-14px;border-right-color:#fff}.Popover-message--right-top::before,.Popover-message--right-top::after,.Popover-message--left-top::before,.Popover-message--left-top::after{top:24px}.Popover-message--right-bottom::before,.Popover-message--right-bottom::after,.Popover-message--left-bottom::before,.Popover-message--left-bottom::after{top:auto}.Popover-message--right-bottom::before,.Popover-message--left-bottom::before{bottom:16px}.Popover-message--right-bottom::after,.Popover-message--left-bottom::after{bottom:17px}@media (min-width: 544px){.Popover-message--large{min-width:320px}}.Progress{display:flex;height:8px;overflow:hidden;background-color:#e1e4e8;border-radius:3px}.Progress--large{height:10px}.Progress--small{height:5px}@media (hover: hover){.SelectMenu-tab:not([aria-checked=\"true\"]):hover,.SelectMenu-tab:not([aria-checked=\"true\"]):active{background-color:#fff}}.SelectMenu{position:fixed;top:0;right:0;bottom:0;left:0;z-index:99;display:flex;padding:16px;pointer-events:none;flex-direction:column}@media (min-width: 544px){.SelectMenu{position:absolute;top:auto;right:auto;bottom:auto;left:auto;padding:0}}.SelectMenu::before{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;content:\"\";background-color:rgba(27,31,35,0.5)}@media (min-width: 544px){.SelectMenu::before{display:none}}.SelectMenu-modal{position:relative;z-index:99;display:flex;max-height:66%;margin:auto 0;overflow:hidden;pointer-events:auto;flex-direction:column;background-color:#f6f8fa;border-radius:6px;box-shadow:0 0 18px rgba(0,0,0,0.4);animation:SelectMenu-modal-animation 0.12s cubic-bezier(0, 0.1, 0.1, 1) backwards}@keyframes SelectMenu-modal-animation{0%{opacity:0;transform:scale(0.9)}}@keyframes SelectMenu-modal-animation--sm{0%{opacity:0;transform:translateY(-16px)}}@media (min-width: 544px){.SelectMenu-modal{width:300px;height:auto;max-height:480px;margin:4px 0 16px 0;font-size:12px;border:1px solid #d1d5da;border-radius:3px;box-shadow:0 1px 5px rgba(27,31,35,0.15);animation-name:SelectMenu-modal-animation--sm}}.SelectMenu-header{display:flex;flex:none;padding:16px}@media (min-width: 544px){.SelectMenu-header{padding-top:8px;padding-bottom:8px}}.SelectMenu-title{flex:auto;font-size:14px;font-weight:600}@media (min-width: 544px){.SelectMenu-title{font-size:inherit}}.SelectMenu-closeButton{padding:16px;margin:-16px;color:#6a737d;background-color:transparent;border:0}@media (min-width: 544px){.SelectMenu-closeButton{display:none}}.SelectMenu-filter{padding:16px;margin:0;border-top:1px #e1e4e8 solid}@media (min-width: 544px){.SelectMenu-filter{padding:8px}}.SelectMenu-input{display:block;width:100%}@media (min-width: 544px){.SelectMenu-input{font-size:14px}}.SelectMenu-list{position:relative;padding:0;margin:0;margin-bottom:-1px;flex:auto;overflow-x:hidden;overflow-y:auto;background-color:#fff;border-top:1px #e1e4e8 solid;-webkit-overflow-scrolling:touch}.SelectMenu-item{display:flex;align-items:center;width:100%;padding:16px;overflow:hidden;color:#586069;text-align:left;cursor:pointer;background-color:#fff;border:0;border-bottom:1px solid #eaecef}@media (min-width: 544px){.SelectMenu-item{padding-top:8px;padding-bottom:8px}}.SelectMenu-icon{width:16px;margin-right:8px;flex-shrink:0}.SelectMenu-icon--check{visibility:hidden;transition:transform 0.12s cubic-bezier(0.5, 0.1, 1, 0.5),visibility 0s 0.12s linear;transform:scale(0)}.SelectMenu-tabs{display:flex;flex-shrink:0;margin-bottom:-1px;overflow-x:auto;overflow-y:hidden;border-top:1px #e1e4e8 solid;-webkit-overflow-scrolling:touch}.SelectMenu-tabs::-webkit-scrollbar{display:none}@media (min-width: 544px){.SelectMenu-tabs{padding:0 8px;border-top:0}}.SelectMenu-tab{flex:1;padding:8px 16px;font-size:12px;font-weight:500;color:#6a737d;text-align:center;background-color:transparent;border:0;box-shadow:inset 0 -1px 0 #e1e4e8}@media (min-width: 544px){.SelectMenu-tab{flex:none;padding:4px 16px;border:1px solid transparent;border-bottom-width:0;border-top-left-radius:3px;border-top-right-radius:3px}}.SelectMenu-tab[aria-selected=\"true\"]{z-index:1;color:#24292e;cursor:default;background-color:#fff;box-shadow:0 0 0 1px #e1e4e8}@media (min-width: 544px){.SelectMenu-tab[aria-selected=\"true\"]{border-color:#e1e4e8;box-shadow:none}}.SelectMenu-message{border-bottom:1px solid #eaecef}.SelectMenu-message,.SelectMenu-blankslate,.SelectMenu-loading{padding:24px 16px;text-align:center;background-color:#fff}.SelectMenu-divider{padding:4px 16px;margin:0;font-size:12px;font-weight:600;color:#6a737d;background-color:#f6f8fa;border-bottom:1px solid #eaecef}.SelectMenu-footer{z-index:0;padding:8px 16px;font-size:12px;color:#6a737d;text-align:center;border-top:1px #e1e4e8 solid}@media (min-width: 544px){.SelectMenu-footer{padding:4px 8px}}.SelectMenu--hasFilter .SelectMenu-modal{height:80%;max-height:none;margin-top:0}@media (min-width: 544px){.SelectMenu--hasFilter .SelectMenu-modal{height:auto;max-height:480px;margin-top:4px}}.SelectMenu-tab:focus,.SelectMenu-item:focus{outline:none}.SelectMenu-item:hover{text-decoration:none}.SelectMenu-item[aria-checked=\"true\"]{font-weight:500;color:#24292e}.SelectMenu-item[aria-checked=\"true\"] .SelectMenu-icon--check{visibility:visible;transition:transform 0.12s cubic-bezier(0, 0, 0.2, 1),visibility 0s linear;transform:scale(1)}@media (hover: hover){body:not(.intent-mouse) .SelectMenu-item:focus,.SelectMenu-item:hover{background-color:#f6f8fa}.SelectMenu-item:active{background-color:#fafbfc}body:not(.intent-mouse) .SelectMenu-tab:focus{background-color:#dbedff}.SelectMenu-tab:not([aria-selected=\"true\"]):hover{color:#24292e;background-color:#e1e4e8}.SelectMenu-tab:not([aria-selected=\"true\"]):active{color:#24292e;background-color:#f6f8fa}}@media (hover: none){.SelectMenu-item:focus,.SelectMenu-item:active{background-color:#fafbfc}.SelectMenu-item{-webkit-tap-highlight-color:rgba(209,213,218,0.5)}}.Subhead{display:flex;padding-bottom:8px;margin-bottom:16px;border-bottom:1px #e1e4e8 solid;flex-flow:row wrap}.Subhead--spacious{margin-top:40px}.Subhead-heading{font-size:24px;font-weight:400;flex:1 1 auto}.Subhead-heading--danger{font-weight:600;color:#cb2431}.Subhead-description{font-size:14px;color:#586069;flex:1 100%}.Subhead-actions{align-self:center;justify-content:flex-end}.TimelineItem{position:relative;display:flex;padding:16px 0;margin-left:16px}.TimelineItem::before{position:absolute;top:0;bottom:0;left:0;display:block;width:2px;content:\"\";background-color:#e1e4e8}.TimelineItem:target .TimelineItem-badge{border-color:#2188ff;box-shadow:0 0 0.2em #c8e1ff}.TimelineItem-badge{position:relative;z-index:1;display:flex;width:32px;height:32px;margin-right:8px;margin-left:-15px;color:#444d56;align-items:center;background-color:#e1e4e8;border:2px solid #fff;border-radius:50%;justify-content:center;flex-shrink:0}.TimelineItem-body{min-width:0;max-width:100%;margin-top:4px;color:#444d56;flex:auto}.TimelineItem-avatar{position:absolute;left:-72px;z-index:1}.TimelineItem-break{position:relative;z-index:1;height:24px;margin:0;margin-bottom:-16px;margin-left:-56px;background-color:#fff;border:0;border-top:4px solid #e1e4e8}.TimelineItem--condensed{padding-top:4px;padding-bottom:0}.TimelineItem--condensed:last-child{padding-bottom:16px}.TimelineItem--condensed .TimelineItem-badge{height:16px;margin-top:8px;margin-bottom:8px;color:#959da5;background-color:#fff;border:0}.Toast{display:flex;margin:8px;color:#1b1f23;background-color:#fff;border-radius:3px;box-shadow:inset 0 0 0 1px #d1d5da,0 1px 5px rgba(27,31,35,0.15)}@media (min-width: 544px){.Toast{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:450px;margin:16px}}.Toast-icon{display:flex;align-items:center;justify-content:center;width:48px;flex-shrink:0;color:#fff;background-color:#0366d6;border-top-left-radius:inherit;border-bottom-left-radius:inherit}.Toast-content{padding:16px}.Toast-dismissButton{max-height:54px;padding:16px;background-color:transparent;border:0}.Toast-dismissButton:focus,.Toast-dismissButton:hover{color:#586069;outline:none}.Toast-dismissButton:active{color:#959da5}.Toast--error .Toast-icon{background-color:#d73a49}.Toast--warning .Toast-icon{color:#24292e;background-color:#f9c513}.Toast--success .Toast-icon{background-color:#28a745}.Toast--loading .Toast-icon{background-color:#586069}.Toast--animateIn{animation:Toast--animateIn 0.18s cubic-bezier(0.22, 0.61, 0.36, 1) backwards}@keyframes Toast--animateIn{0%{opacity:0;transform:translateY(100%)}}.Toast--animateOut{animation:Toast--animateOut 0.18s cubic-bezier(0.55, 0.06, 0.68, 0.19) forwards}@keyframes Toast--animateOut{100%{pointer-events:none;opacity:0;transform:translateY(100%)}}.Toast--spinner{animation:Toast--spinner 1000ms linear infinite}@keyframes Toast--spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}/*!\n * @primer/css/marketing\n * http://primer.style/css\n *\n * Released under MIT license. Copyright (c) 2019 GitHub Inc.\n */@font-face{font-family:Inter;font-style:normal;font-weight:400;src:local(\"Inter\"),local(\"Inter-Regular\"),url(\"/fonts/Inter-Regular.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:500;src:local(\"Inter Medium\"),local(\"Inter-Medium\"),url(\"/fonts/Inter-Medium.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:600;src:local(\"Inter Bold\"),local(\"Inter-Bold\"),url(\"/fonts/Inter-Bold.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:400;src:local(\"Inter\"),local(\"Inter-Regular\"),url(\"/fonts/Inter-Regular.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:500;src:local(\"Inter Medium\"),local(\"Inter-Medium\"),url(\"/fonts/Inter-Medium.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:600;src:local(\"Inter Bold\"),local(\"Inter-Bold\"),url(\"/fonts/Inter-Bold.woff\") format(\"woff\");font-display:swap}.h000-mktg,.h00-mktg,.h0-mktg,.h1-mktg,.h2-mktg,.h3-mktg,.h4-mktg,.h5-mktg,.h6-mktg,.lead-mktg{font-family:Inter,-apple-system,BlinkMacSystemFont,\"Segoe UI\",Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\";font-weight:500}.h000-mktg{font-size:48px !important}@media (min-width: 768px){.h000-mktg{font-size:64px !important}}.h00-mktg{font-size:40px !important}@media (min-width: 768px){.h00-mktg{font-size:48px !important}}.h0-mktg{font-size:32px !important}@media (min-width: 768px){.h0-mktg{font-size:40px !important}}.h1-mktg{font-size:26px !important}@media (min-width: 768px){.h1-mktg{font-size:32px !important}}.h2-mktg{font-size:22px !important}@media (min-width: 768px){.h2-mktg{font-size:24px !important}}.h3-mktg{font-size:18px !important}@media (min-width: 768px){.h3-mktg{font-size:20px !important}}.h4-mktg{font-size:16px !important}.h5-mktg{font-size:14px !important}.h6-mktg{font-size:12px !important}.lead-mktg{font-size:20px;font-weight:400}.pullquote{padding-top:0;padding-bottom:0;padding-left:8px;margin-bottom:24px;font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",Menlo,monospace;font-size:16px;line-height:1.4;color:#586069;border-left:3px solid #e1e4e8}@media (min-width: 768px){.pullquote{padding-left:12px;margin-bottom:32px;margin-left:-15px;font-size:18px;line-height:1.5}}@font-face{font-family:Inter;font-style:normal;font-weight:400;src:local(\"Inter\"),local(\"Inter-Regular\"),url(\"/fonts/Inter-Regular.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:500;src:local(\"Inter Medium\"),local(\"Inter-Medium\"),url(\"/fonts/Inter-Medium.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:600;src:local(\"Inter Bold\"),local(\"Inter-Bold\"),url(\"/fonts/Inter-Bold.woff\") format(\"woff\");font-display:swap}.btn-mktg{display:inline-block;padding:16px 24px;font-size:14px;font-weight:500;color:#fff;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#1074e7;border:1px solid #1074e7;border-radius:3px;transition:.2s;-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-mktg:hover{text-decoration:none;background-color:#0366d6;border-color:#0366d6}.btn-mktg:focus{outline:0;box-shadow:0 0 0 0.2em rgba(3,102,214,0.3)}.btn-mktg:disabled,.btn-mktg.disabled,.btn-mktg[aria-disabled=true]{pointer-events:none;cursor:default;opacity:0.65}.btn-primary-mktg{background-color:#2ebc4f;border-color:#2ebc4f}.btn-primary-mktg:hover{background-color:#28a745;border-color:#28a745}.btn-primary-mktg:focus{box-shadow:0 0 0 0.2em rgba(40,167,69,0.3)}.btn-large-mktg{padding:20px 32px;font-size:16px}.btn-outline-mktg{color:#1074e7;background-color:rgba(255,255,255,0);border-color:rgba(16,116,231,0.5)}.btn-outline-mktg:hover{color:#0366d6;text-decoration:none;background-color:rgba(255,255,255,0);border-color:#1074e7}.btn-transparent{color:#fff;background-color:transparent;background-image:none;border:1px solid rgba(255,255,255,0.5)}.btn-transparent:hover,.btn-transparent:active{color:#2f363d;background-color:#fff;background-image:none;border-color:#fff}@font-face{font-family:Inter;font-style:normal;font-weight:400;src:local(\"Inter\"),local(\"Inter-Regular\"),url(\"/fonts/Inter-Regular.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:500;src:local(\"Inter Medium\"),local(\"Inter-Medium\"),url(\"/fonts/Inter-Medium.woff\") format(\"woff\");font-display:swap}@font-face{font-family:Inter;font-style:normal;font-weight:600;src:local(\"Inter Bold\"),local(\"Inter-Bold\"),url(\"/fonts/Inter-Bold.woff\") format(\"woff\");font-display:swap}.grayscale{filter:grayscale(100%)}.top-0{top:0 !important}.right-0{right:0 !important}.bottom-0{bottom:0 !important}.left-0{left:0 !important}.top-n0{top:0 !important}.right-n0{right:0 !important}.bottom-n0{bottom:0 !important}.left-n0{left:0 !important}.top-1{top:4px !important}.right-1{right:4px !important}.bottom-1{bottom:4px !important}.left-1{left:4px !important}.top-n1{top:-4px !important}.right-n1{right:-4px !important}.bottom-n1{bottom:-4px !important}.left-n1{left:-4px !important}.top-2{top:8px !important}.right-2{right:8px !important}.bottom-2{bottom:8px !important}.left-2{left:8px !important}.top-n2{top:-8px !important}.right-n2{right:-8px !important}.bottom-n2{bottom:-8px !important}.left-n2{left:-8px !important}.top-3{top:16px !important}.right-3{right:16px !important}.bottom-3{bottom:16px !important}.left-3{left:16px !important}.top-n3{top:-16px !important}.right-n3{right:-16px !important}.bottom-n3{bottom:-16px !important}.left-n3{left:-16px !important}.top-4{top:24px !important}.right-4{right:24px !important}.bottom-4{bottom:24px !important}.left-4{left:24px !important}.top-n4{top:-24px !important}.right-n4{right:-24px !important}.bottom-n4{bottom:-24px !important}.left-n4{left:-24px !important}.top-5{top:32px !important}.right-5{right:32px !important}.bottom-5{bottom:32px !important}.left-5{left:32px !important}.top-n5{top:-32px !important}.right-n5{right:-32px !important}.bottom-n5{bottom:-32px !important}.left-n5{left:-32px !important}.top-6{top:40px !important}.right-6{right:40px !important}.bottom-6{bottom:40px !important}.left-6{left:40px !important}.top-n6{top:-40px !important}.right-n6{right:-40px !important}.bottom-n6{bottom:-40px !important}.left-n6{left:-40px !important}.top-7{top:48px !important}.right-7{right:48px !important}.bottom-7{bottom:48px !important}.left-7{left:48px !important}.top-n7{top:-48px !important}.right-n7{right:-48px !important}.bottom-n7{bottom:-48px !important}.left-n7{left:-48px !important}.top-8{top:64px !important}.right-8{right:64px !important}.bottom-8{bottom:64px !important}.left-8{left:64px !important}.top-n8{top:-64px !important}.right-n8{right:-64px !important}.bottom-n8{bottom:-64px !important}.left-n8{left:-64px !important}.top-9{top:80px !important}.right-9{right:80px !important}.bottom-9{bottom:80px !important}.left-9{left:80px !important}.top-n9{top:-80px !important}.right-n9{right:-80px !important}.bottom-n9{bottom:-80px !important}.left-n9{left:-80px !important}.top-10{top:96px !important}.right-10{right:96px !important}.bottom-10{bottom:96px !important}.left-10{left:96px !important}.top-n10{top:-96px !important}.right-n10{right:-96px !important}.bottom-n10{bottom:-96px !important}.left-n10{left:-96px !important}.top-11{top:112px !important}.right-11{right:112px !important}.bottom-11{bottom:112px !important}.left-11{left:112px !important}.top-n11{top:-112px !important}.right-n11{right:-112px !important}.bottom-n11{bottom:-112px !important}.left-n11{left:-112px !important}.top-12{top:128px !important}.right-12{right:128px !important}.bottom-12{bottom:128px !important}.left-12{left:128px !important}.top-n12{top:-128px !important}.right-n12{right:-128px !important}.bottom-n12{bottom:-128px !important}.left-n12{left:-128px !important}@media (min-width: 768px){.top-md-0{top:0 !important}.right-md-0{right:0 !important}.bottom-md-0{bottom:0 !important}.left-md-0{left:0 !important}.top-md-n0{top:0 !important}.right-md-n0{right:0 !important}.bottom-md-n0{bottom:0 !important}.left-md-n0{left:0 !important}.top-md-1{top:4px !important}.right-md-1{right:4px !important}.bottom-md-1{bottom:4px !important}.left-md-1{left:4px !important}.top-md-n1{top:-4px !important}.right-md-n1{right:-4px !important}.bottom-md-n1{bottom:-4px !important}.left-md-n1{left:-4px !important}.top-md-2{top:8px !important}.right-md-2{right:8px !important}.bottom-md-2{bottom:8px !important}.left-md-2{left:8px !important}.top-md-n2{top:-8px !important}.right-md-n2{right:-8px !important}.bottom-md-n2{bottom:-8px !important}.left-md-n2{left:-8px !important}.top-md-3{top:16px !important}.right-md-3{right:16px !important}.bottom-md-3{bottom:16px !important}.left-md-3{left:16px !important}.top-md-n3{top:-16px !important}.right-md-n3{right:-16px !important}.bottom-md-n3{bottom:-16px !important}.left-md-n3{left:-16px !important}.top-md-4{top:24px !important}.right-md-4{right:24px !important}.bottom-md-4{bottom:24px !important}.left-md-4{left:24px !important}.top-md-n4{top:-24px !important}.right-md-n4{right:-24px !important}.bottom-md-n4{bottom:-24px !important}.left-md-n4{left:-24px !important}.top-md-5{top:32px !important}.right-md-5{right:32px !important}.bottom-md-5{bottom:32px !important}.left-md-5{left:32px !important}.top-md-n5{top:-32px !important}.right-md-n5{right:-32px !important}.bottom-md-n5{bottom:-32px !important}.left-md-n5{left:-32px !important}.top-md-6{top:40px !important}.right-md-6{right:40px !important}.bottom-md-6{bottom:40px !important}.left-md-6{left:40px !important}.top-md-n6{top:-40px !important}.right-md-n6{right:-40px !important}.bottom-md-n6{bottom:-40px !important}.left-md-n6{left:-40px !important}.top-md-7{top:48px !important}.right-md-7{right:48px !important}.bottom-md-7{bottom:48px !important}.left-md-7{left:48px !important}.top-md-n7{top:-48px !important}.right-md-n7{right:-48px !important}.bottom-md-n7{bottom:-48px !important}.left-md-n7{left:-48px !important}.top-md-8{top:64px !important}.right-md-8{right:64px !important}.bottom-md-8{bottom:64px !important}.left-md-8{left:64px !important}.top-md-n8{top:-64px !important}.right-md-n8{right:-64px !important}.bottom-md-n8{bottom:-64px !important}.left-md-n8{left:-64px !important}.top-md-9{top:80px !important}.right-md-9{right:80px !important}.bottom-md-9{bottom:80px !important}.left-md-9{left:80px !important}.top-md-n9{top:-80px !important}.right-md-n9{right:-80px !important}.bottom-md-n9{bottom:-80px !important}.left-md-n9{left:-80px !important}.top-md-10{top:96px !important}.right-md-10{right:96px !important}.bottom-md-10{bottom:96px !important}.left-md-10{left:96px !important}.top-md-n10{top:-96px !important}.right-md-n10{right:-96px !important}.bottom-md-n10{bottom:-96px !important}.left-md-n10{left:-96px !important}.top-md-11{top:112px !important}.right-md-11{right:112px !important}.bottom-md-11{bottom:112px !important}.left-md-11{left:112px !important}.top-md-n11{top:-112px !important}.right-md-n11{right:-112px !important}.bottom-md-n11{bottom:-112px !important}.left-md-n11{left:-112px !important}.top-md-12{top:128px !important}.right-md-12{right:128px !important}.bottom-md-12{bottom:128px !important}.left-md-12{left:128px !important}.top-md-n12{top:-128px !important}.right-md-n12{right:-128px !important}.bottom-md-n12{bottom:-128px !important}.left-md-n12{left:-128px !important}}@media (min-width: 1012px){.top-lg-0{top:0 !important}.right-lg-0{right:0 !important}.bottom-lg-0{bottom:0 !important}.left-lg-0{left:0 !important}.top-lg-n0{top:0 !important}.right-lg-n0{right:0 !important}.bottom-lg-n0{bottom:0 !important}.left-lg-n0{left:0 !important}.top-lg-1{top:4px !important}.right-lg-1{right:4px !important}.bottom-lg-1{bottom:4px !important}.left-lg-1{left:4px !important}.top-lg-n1{top:-4px !important}.right-lg-n1{right:-4px !important}.bottom-lg-n1{bottom:-4px !important}.left-lg-n1{left:-4px !important}.top-lg-2{top:8px !important}.right-lg-2{right:8px !important}.bottom-lg-2{bottom:8px !important}.left-lg-2{left:8px !important}.top-lg-n2{top:-8px !important}.right-lg-n2{right:-8px !important}.bottom-lg-n2{bottom:-8px !important}.left-lg-n2{left:-8px !important}.top-lg-3{top:16px !important}.right-lg-3{right:16px !important}.bottom-lg-3{bottom:16px !important}.left-lg-3{left:16px !important}.top-lg-n3{top:-16px !important}.right-lg-n3{right:-16px !important}.bottom-lg-n3{bottom:-16px !important}.left-lg-n3{left:-16px !important}.top-lg-4{top:24px !important}.right-lg-4{right:24px !important}.bottom-lg-4{bottom:24px !important}.left-lg-4{left:24px !important}.top-lg-n4{top:-24px !important}.right-lg-n4{right:-24px !important}.bottom-lg-n4{bottom:-24px !important}.left-lg-n4{left:-24px !important}.top-lg-5{top:32px !important}.right-lg-5{right:32px !important}.bottom-lg-5{bottom:32px !important}.left-lg-5{left:32px !important}.top-lg-n5{top:-32px !important}.right-lg-n5{right:-32px !important}.bottom-lg-n5{bottom:-32px !important}.left-lg-n5{left:-32px !important}.top-lg-6{top:40px !important}.right-lg-6{right:40px !important}.bottom-lg-6{bottom:40px !important}.left-lg-6{left:40px !important}.top-lg-n6{top:-40px !important}.right-lg-n6{right:-40px !important}.bottom-lg-n6{bottom:-40px !important}.left-lg-n6{left:-40px !important}.top-lg-7{top:48px !important}.right-lg-7{right:48px !important}.bottom-lg-7{bottom:48px !important}.left-lg-7{left:48px !important}.top-lg-n7{top:-48px !important}.right-lg-n7{right:-48px !important}.bottom-lg-n7{bottom:-48px !important}.left-lg-n7{left:-48px !important}.top-lg-8{top:64px !important}.right-lg-8{right:64px !important}.bottom-lg-8{bottom:64px !important}.left-lg-8{left:64px !important}.top-lg-n8{top:-64px !important}.right-lg-n8{right:-64px !important}.bottom-lg-n8{bottom:-64px !important}.left-lg-n8{left:-64px !important}.top-lg-9{top:80px !important}.right-lg-9{right:80px !important}.bottom-lg-9{bottom:80px !important}.left-lg-9{left:80px !important}.top-lg-n9{top:-80px !important}.right-lg-n9{right:-80px !important}.bottom-lg-n9{bottom:-80px !important}.left-lg-n9{left:-80px !important}.top-lg-10{top:96px !important}.right-lg-10{right:96px !important}.bottom-lg-10{bottom:96px !important}.left-lg-10{left:96px !important}.top-lg-n10{top:-96px !important}.right-lg-n10{right:-96px !important}.bottom-lg-n10{bottom:-96px !important}.left-lg-n10{left:-96px !important}.top-lg-11{top:112px !important}.right-lg-11{right:112px !important}.bottom-lg-11{bottom:112px !important}.left-lg-11{left:112px !important}.top-lg-n11{top:-112px !important}.right-lg-n11{right:-112px !important}.bottom-lg-n11{bottom:-112px !important}.left-lg-n11{left:-112px !important}.top-lg-12{top:128px !important}.right-lg-12{right:128px !important}.bottom-lg-12{bottom:128px !important}.left-lg-12{left:128px !important}.top-lg-n12{top:-128px !important}.right-lg-n12{right:-128px !important}.bottom-lg-n12{bottom:-128px !important}.left-lg-n12{left:-128px !important}}.offset-n1{margin-left:-8.33333%}.offset-n2{margin-left:-16.66667%}.offset-n3{margin-left:-25%}.offset-n4{margin-left:-33.33333%}.offset-n5{margin-left:-41.66667%}.offset-n6{margin-left:-50%}.offset-n7{margin-left:-58.33333%}@media (min-width: 544px){.offset-sm-n1{margin-left:-8.33333%}.offset-sm-n2{margin-left:-16.66667%}.offset-sm-n3{margin-left:-25%}.offset-sm-n4{margin-left:-33.33333%}.offset-sm-n5{margin-left:-41.66667%}.offset-sm-n6{margin-left:-50%}.offset-sm-n7{margin-left:-58.33333%}}@media (min-width: 768px){.offset-md-n1{margin-left:-8.33333%}.offset-md-n2{margin-left:-16.66667%}.offset-md-n3{margin-left:-25%}.offset-md-n4{margin-left:-33.33333%}.offset-md-n5{margin-left:-41.66667%}.offset-md-n6{margin-left:-50%}.offset-md-n7{margin-left:-58.33333%}}@media (min-width: 1012px){.offset-lg-n1{margin-left:-8.33333%}.offset-lg-n2{margin-left:-16.66667%}.offset-lg-n3{margin-left:-25%}.offset-lg-n4{margin-left:-33.33333%}.offset-lg-n5{margin-left:-41.66667%}.offset-lg-n6{margin-left:-50%}.offset-lg-n7{margin-left:-58.33333%}}@media (min-width: 1280px){.offset-xl-n1{margin-left:-8.33333%}.offset-xl-n2{margin-left:-16.66667%}.offset-xl-n3{margin-left:-25%}.offset-xl-n4{margin-left:-33.33333%}.offset-xl-n5{margin-left:-41.66667%}.offset-xl-n6{margin-left:-50%}.offset-xl-n7{margin-left:-58.33333%}}.mt-0{margin-top:0 !important}.mb-0{margin-bottom:0 !important}.my-0{margin-top:0 !important;margin-bottom:0 !important}.mt-1{margin-top:4px !important}.mb-1{margin-bottom:4px !important}.my-1{margin-top:4px !important;margin-bottom:4px !important}.mt-2{margin-top:8px !important}.mb-2{margin-bottom:8px !important}.my-2{margin-top:8px !important;margin-bottom:8px !important}.mt-3{margin-top:16px !important}.mb-3{margin-bottom:16px !important}.my-3{margin-top:16px !important;margin-bottom:16px !important}.mt-4{margin-top:24px !important}.mb-4{margin-bottom:24px !important}.my-4{margin-top:24px !important;margin-bottom:24px !important}.mt-5{margin-top:32px !important}.mb-5{margin-bottom:32px !important}.my-5{margin-top:32px !important;margin-bottom:32px !important}.mt-6{margin-top:40px !important}.mb-6{margin-bottom:40px !important}.my-6{margin-top:40px !important;margin-bottom:40px !important}.mt-7{margin-top:48px !important}.mb-7{margin-bottom:48px !important}.my-7{margin-top:48px !important;margin-bottom:48px !important}.mt-8{margin-top:64px !important}.mb-8{margin-bottom:64px !important}.my-8{margin-top:64px !important;margin-bottom:64px !important}.mt-9{margin-top:80px !important}.mb-9{margin-bottom:80px !important}.my-9{margin-top:80px !important;margin-bottom:80px !important}.mt-10{margin-top:96px !important}.mb-10{margin-bottom:96px !important}.my-10{margin-top:96px !important;margin-bottom:96px !important}.mt-11{margin-top:112px !important}.mb-11{margin-bottom:112px !important}.my-11{margin-top:112px !important;margin-bottom:112px !important}.mt-12{margin-top:128px !important}.mb-12{margin-bottom:128px !important}.my-12{margin-top:128px !important;margin-bottom:128px !important}@media (min-width: 544px){.mt-sm-0{margin-top:0 !important}.mb-sm-0{margin-bottom:0 !important}.my-sm-0{margin-top:0 !important;margin-bottom:0 !important}.mt-sm-1{margin-top:4px !important}.mb-sm-1{margin-bottom:4px !important}.my-sm-1{margin-top:4px !important;margin-bottom:4px !important}.mt-sm-2{margin-top:8px !important}.mb-sm-2{margin-bottom:8px !important}.my-sm-2{margin-top:8px !important;margin-bottom:8px !important}.mt-sm-3{margin-top:16px !important}.mb-sm-3{margin-bottom:16px !important}.my-sm-3{margin-top:16px !important;margin-bottom:16px !important}.mt-sm-4{margin-top:24px !important}.mb-sm-4{margin-bottom:24px !important}.my-sm-4{margin-top:24px !important;margin-bottom:24px !important}.mt-sm-5{margin-top:32px !important}.mb-sm-5{margin-bottom:32px !important}.my-sm-5{margin-top:32px !important;margin-bottom:32px !important}.mt-sm-6{margin-top:40px !important}.mb-sm-6{margin-bottom:40px !important}.my-sm-6{margin-top:40px !important;margin-bottom:40px !important}.mt-sm-7{margin-top:48px !important}.mb-sm-7{margin-bottom:48px !important}.my-sm-7{margin-top:48px !important;margin-bottom:48px !important}.mt-sm-8{margin-top:64px !important}.mb-sm-8{margin-bottom:64px !important}.my-sm-8{margin-top:64px !important;margin-bottom:64px !important}.mt-sm-9{margin-top:80px !important}.mb-sm-9{margin-bottom:80px !important}.my-sm-9{margin-top:80px !important;margin-bottom:80px !important}.mt-sm-10{margin-top:96px !important}.mb-sm-10{margin-bottom:96px !important}.my-sm-10{margin-top:96px !important;margin-bottom:96px !important}.mt-sm-11{margin-top:112px !important}.mb-sm-11{margin-bottom:112px !important}.my-sm-11{margin-top:112px !important;margin-bottom:112px !important}.mt-sm-12{margin-top:128px !important}.mb-sm-12{margin-bottom:128px !important}.my-sm-12{margin-top:128px !important;margin-bottom:128px !important}}@media (min-width: 768px){.mt-md-0{margin-top:0 !important}.mb-md-0{margin-bottom:0 !important}.my-md-0{margin-top:0 !important;margin-bottom:0 !important}.mt-md-1{margin-top:4px !important}.mb-md-1{margin-bottom:4px !important}.my-md-1{margin-top:4px !important;margin-bottom:4px !important}.mt-md-2{margin-top:8px !important}.mb-md-2{margin-bottom:8px !important}.my-md-2{margin-top:8px !important;margin-bottom:8px !important}.mt-md-3{margin-top:16px !important}.mb-md-3{margin-bottom:16px !important}.my-md-3{margin-top:16px !important;margin-bottom:16px !important}.mt-md-4{margin-top:24px !important}.mb-md-4{margin-bottom:24px !important}.my-md-4{margin-top:24px !important;margin-bottom:24px !important}.mt-md-5{margin-top:32px !important}.mb-md-5{margin-bottom:32px !important}.my-md-5{margin-top:32px !important;margin-bottom:32px !important}.mt-md-6{margin-top:40px !important}.mb-md-6{margin-bottom:40px !important}.my-md-6{margin-top:40px !important;margin-bottom:40px !important}.mt-md-7{margin-top:48px !important}.mb-md-7{margin-bottom:48px !important}.my-md-7{margin-top:48px !important;margin-bottom:48px !important}.mt-md-8{margin-top:64px !important}.mb-md-8{margin-bottom:64px !important}.my-md-8{margin-top:64px !important;margin-bottom:64px !important}.mt-md-9{margin-top:80px !important}.mb-md-9{margin-bottom:80px !important}.my-md-9{margin-top:80px !important;margin-bottom:80px !important}.mt-md-10{margin-top:96px !important}.mb-md-10{margin-bottom:96px !important}.my-md-10{margin-top:96px !important;margin-bottom:96px !important}.mt-md-11{margin-top:112px !important}.mb-md-11{margin-bottom:112px !important}.my-md-11{margin-top:112px !important;margin-bottom:112px !important}.mt-md-12{margin-top:128px !important}.mb-md-12{margin-bottom:128px !important}.my-md-12{margin-top:128px !important;margin-bottom:128px !important}}@media (min-width: 1012px){.mt-lg-0{margin-top:0 !important}.mb-lg-0{margin-bottom:0 !important}.my-lg-0{margin-top:0 !important;margin-bottom:0 !important}.mt-lg-1{margin-top:4px !important}.mb-lg-1{margin-bottom:4px !important}.my-lg-1{margin-top:4px !important;margin-bottom:4px !important}.mt-lg-2{margin-top:8px !important}.mb-lg-2{margin-bottom:8px !important}.my-lg-2{margin-top:8px !important;margin-bottom:8px !important}.mt-lg-3{margin-top:16px !important}.mb-lg-3{margin-bottom:16px !important}.my-lg-3{margin-top:16px !important;margin-bottom:16px !important}.mt-lg-4{margin-top:24px !important}.mb-lg-4{margin-bottom:24px !important}.my-lg-4{margin-top:24px !important;margin-bottom:24px !important}.mt-lg-5{margin-top:32px !important}.mb-lg-5{margin-bottom:32px !important}.my-lg-5{margin-top:32px !important;margin-bottom:32px !important}.mt-lg-6{margin-top:40px !important}.mb-lg-6{margin-bottom:40px !important}.my-lg-6{margin-top:40px !important;margin-bottom:40px !important}.mt-lg-7{margin-top:48px !important}.mb-lg-7{margin-bottom:48px !important}.my-lg-7{margin-top:48px !important;margin-bottom:48px !important}.mt-lg-8{margin-top:64px !important}.mb-lg-8{margin-bottom:64px !important}.my-lg-8{margin-top:64px !important;margin-bottom:64px !important}.mt-lg-9{margin-top:80px !important}.mb-lg-9{margin-bottom:80px !important}.my-lg-9{margin-top:80px !important;margin-bottom:80px !important}.mt-lg-10{margin-top:96px !important}.mb-lg-10{margin-bottom:96px !important}.my-lg-10{margin-top:96px !important;margin-bottom:96px !important}.mt-lg-11{margin-top:112px !important}.mb-lg-11{margin-bottom:112px !important}.my-lg-11{margin-top:112px !important;margin-bottom:112px !important}.mt-lg-12{margin-top:128px !important}.mb-lg-12{margin-bottom:128px !important}.my-lg-12{margin-top:128px !important;margin-bottom:128px !important}}@media (min-width: 1280px){.mt-xl-0{margin-top:0 !important}.mb-xl-0{margin-bottom:0 !important}.my-xl-0{margin-top:0 !important;margin-bottom:0 !important}.mt-xl-1{margin-top:4px !important}.mb-xl-1{margin-bottom:4px !important}.my-xl-1{margin-top:4px !important;margin-bottom:4px !important}.mt-xl-2{margin-top:8px !important}.mb-xl-2{margin-bottom:8px !important}.my-xl-2{margin-top:8px !important;margin-bottom:8px !important}.mt-xl-3{margin-top:16px !important}.mb-xl-3{margin-bottom:16px !important}.my-xl-3{margin-top:16px !important;margin-bottom:16px !important}.mt-xl-4{margin-top:24px !important}.mb-xl-4{margin-bottom:24px !important}.my-xl-4{margin-top:24px !important;margin-bottom:24px !important}.mt-xl-5{margin-top:32px !important}.mb-xl-5{margin-bottom:32px !important}.my-xl-5{margin-top:32px !important;margin-bottom:32px !important}.mt-xl-6{margin-top:40px !important}.mb-xl-6{margin-bottom:40px !important}.my-xl-6{margin-top:40px !important;margin-bottom:40px !important}.mt-xl-7{margin-top:48px !important}.mb-xl-7{margin-bottom:48px !important}.my-xl-7{margin-top:48px !important;margin-bottom:48px !important}.mt-xl-8{margin-top:64px !important}.mb-xl-8{margin-bottom:64px !important}.my-xl-8{margin-top:64px !important;margin-bottom:64px !important}.mt-xl-9{margin-top:80px !important}.mb-xl-9{margin-bottom:80px !important}.my-xl-9{margin-top:80px !important;margin-bottom:80px !important}.mt-xl-10{margin-top:96px !important}.mb-xl-10{margin-bottom:96px !important}.my-xl-10{margin-top:96px !important;margin-bottom:96px !important}.mt-xl-11{margin-top:112px !important}.mb-xl-11{margin-bottom:112px !important}.my-xl-11{margin-top:112px !important;margin-bottom:112px !important}.mt-xl-12{margin-top:128px !important}.mb-xl-12{margin-bottom:128px !important}.my-xl-12{margin-top:128px !important;margin-bottom:128px !important}}.p-0{padding:0 !important}.pt-0{padding-top:0 !important}.pr-0{padding-right:0 !important}.pb-0{padding-bottom:0 !important}.pl-0{padding-left:0 !important}.py-0{padding-top:0 !important;padding-bottom:0 !important}.p-1{padding:4px !important}.pt-1{padding-top:4px !important}.pr-1{padding-right:4px !important}.pb-1{padding-bottom:4px !important}.pl-1{padding-left:4px !important}.py-1{padding-top:4px !important;padding-bottom:4px !important}.p-2{padding:8px !important}.pt-2{padding-top:8px !important}.pr-2{padding-right:8px !important}.pb-2{padding-bottom:8px !important}.pl-2{padding-left:8px !important}.py-2{padding-top:8px !important;padding-bottom:8px !important}.p-3{padding:16px !important}.pt-3{padding-top:16px !important}.pr-3{padding-right:16px !important}.pb-3{padding-bottom:16px !important}.pl-3{padding-left:16px !important}.py-3{padding-top:16px !important;padding-bottom:16px !important}.p-4{padding:24px !important}.pt-4{padding-top:24px !important}.pr-4{padding-right:24px !important}.pb-4{padding-bottom:24px !important}.pl-4{padding-left:24px !important}.py-4{padding-top:24px !important;padding-bottom:24px !important}.p-5{padding:32px !important}.pt-5{padding-top:32px !important}.pr-5{padding-right:32px !important}.pb-5{padding-bottom:32px !important}.pl-5{padding-left:32px !important}.py-5{padding-top:32px !important;padding-bottom:32px !important}.p-6{padding:40px !important}.pt-6{padding-top:40px !important}.pr-6{padding-right:40px !important}.pb-6{padding-bottom:40px !important}.pl-6{padding-left:40px !important}.py-6{padding-top:40px !important;padding-bottom:40px !important}.p-7{padding:48px !important}.pt-7{padding-top:48px !important}.pr-7{padding-right:48px !important}.pb-7{padding-bottom:48px !important}.pl-7{padding-left:48px !important}.py-7{padding-top:48px !important;padding-bottom:48px !important}.p-8{padding:64px !important}.pt-8{padding-top:64px !important}.pr-8{padding-right:64px !important}.pb-8{padding-bottom:64px !important}.pl-8{padding-left:64px !important}.py-8{padding-top:64px !important;padding-bottom:64px !important}.p-9{padding:80px !important}.pt-9{padding-top:80px !important}.pr-9{padding-right:80px !important}.pb-9{padding-bottom:80px !important}.pl-9{padding-left:80px !important}.py-9{padding-top:80px !important;padding-bottom:80px !important}.p-10{padding:96px !important}.pt-10{padding-top:96px !important}.pr-10{padding-right:96px !important}.pb-10{padding-bottom:96px !important}.pl-10{padding-left:96px !important}.py-10{padding-top:96px !important;padding-bottom:96px !important}.p-11{padding:112px !important}.pt-11{padding-top:112px !important}.pr-11{padding-right:112px !important}.pb-11{padding-bottom:112px !important}.pl-11{padding-left:112px !important}.py-11{padding-top:112px !important;padding-bottom:112px !important}.p-12{padding:128px !important}.pt-12{padding-top:128px !important}.pr-12{padding-right:128px !important}.pb-12{padding-bottom:128px !important}.pl-12{padding-left:128px !important}.py-12{padding-top:128px !important;padding-bottom:128px !important}@media (min-width: 544px){.p-sm-0{padding:0 !important}.pt-sm-0{padding-top:0 !important}.pr-sm-0{padding-right:0 !important}.pb-sm-0{padding-bottom:0 !important}.pl-sm-0{padding-left:0 !important}.py-sm-0{padding-top:0 !important;padding-bottom:0 !important}.p-sm-1{padding:4px !important}.pt-sm-1{padding-top:4px !important}.pr-sm-1{padding-right:4px !important}.pb-sm-1{padding-bottom:4px !important}.pl-sm-1{padding-left:4px !important}.py-sm-1{padding-top:4px !important;padding-bottom:4px !important}.p-sm-2{padding:8px !important}.pt-sm-2{padding-top:8px !important}.pr-sm-2{padding-right:8px !important}.pb-sm-2{padding-bottom:8px !important}.pl-sm-2{padding-left:8px !important}.py-sm-2{padding-top:8px !important;padding-bottom:8px !important}.p-sm-3{padding:16px !important}.pt-sm-3{padding-top:16px !important}.pr-sm-3{padding-right:16px !important}.pb-sm-3{padding-bottom:16px !important}.pl-sm-3{padding-left:16px !important}.py-sm-3{padding-top:16px !important;padding-bottom:16px !important}.p-sm-4{padding:24px !important}.pt-sm-4{padding-top:24px !important}.pr-sm-4{padding-right:24px !important}.pb-sm-4{padding-bottom:24px !important}.pl-sm-4{padding-left:24px !important}.py-sm-4{padding-top:24px !important;padding-bottom:24px !important}.p-sm-5{padding:32px !important}.pt-sm-5{padding-top:32px !important}.pr-sm-5{padding-right:32px !important}.pb-sm-5{padding-bottom:32px !important}.pl-sm-5{padding-left:32px !important}.py-sm-5{padding-top:32px !important;padding-bottom:32px !important}.p-sm-6{padding:40px !important}.pt-sm-6{padding-top:40px !important}.pr-sm-6{padding-right:40px !important}.pb-sm-6{padding-bottom:40px !important}.pl-sm-6{padding-left:40px !important}.py-sm-6{padding-top:40px !important;padding-bottom:40px !important}.p-sm-7{padding:48px !important}.pt-sm-7{padding-top:48px !important}.pr-sm-7{padding-right:48px !important}.pb-sm-7{padding-bottom:48px !important}.pl-sm-7{padding-left:48px !important}.py-sm-7{padding-top:48px !important;padding-bottom:48px !important}.p-sm-8{padding:64px !important}.pt-sm-8{padding-top:64px !important}.pr-sm-8{padding-right:64px !important}.pb-sm-8{padding-bottom:64px !important}.pl-sm-8{padding-left:64px !important}.py-sm-8{padding-top:64px !important;padding-bottom:64px !important}.p-sm-9{padding:80px !important}.pt-sm-9{padding-top:80px !important}.pr-sm-9{padding-right:80px !important}.pb-sm-9{padding-bottom:80px !important}.pl-sm-9{padding-left:80px !important}.py-sm-9{padding-top:80px !important;padding-bottom:80px !important}.p-sm-10{padding:96px !important}.pt-sm-10{padding-top:96px !important}.pr-sm-10{padding-right:96px !important}.pb-sm-10{padding-bottom:96px !important}.pl-sm-10{padding-left:96px !important}.py-sm-10{padding-top:96px !important;padding-bottom:96px !important}.p-sm-11{padding:112px !important}.pt-sm-11{padding-top:112px !important}.pr-sm-11{padding-right:112px !important}.pb-sm-11{padding-bottom:112px !important}.pl-sm-11{padding-left:112px !important}.py-sm-11{padding-top:112px !important;padding-bottom:112px !important}.p-sm-12{padding:128px !important}.pt-sm-12{padding-top:128px !important}.pr-sm-12{padding-right:128px !important}.pb-sm-12{padding-bottom:128px !important}.pl-sm-12{padding-left:128px !important}.py-sm-12{padding-top:128px !important;padding-bottom:128px !important}}@media (min-width: 768px){.p-md-0{padding:0 !important}.pt-md-0{padding-top:0 !important}.pr-md-0{padding-right:0 !important}.pb-md-0{padding-bottom:0 !important}.pl-md-0{padding-left:0 !important}.py-md-0{padding-top:0 !important;padding-bottom:0 !important}.p-md-1{padding:4px !important}.pt-md-1{padding-top:4px !important}.pr-md-1{padding-right:4px !important}.pb-md-1{padding-bottom:4px !important}.pl-md-1{padding-left:4px !important}.py-md-1{padding-top:4px !important;padding-bottom:4px !important}.p-md-2{padding:8px !important}.pt-md-2{padding-top:8px !important}.pr-md-2{padding-right:8px !important}.pb-md-2{padding-bottom:8px !important}.pl-md-2{padding-left:8px !important}.py-md-2{padding-top:8px !important;padding-bottom:8px !important}.p-md-3{padding:16px !important}.pt-md-3{padding-top:16px !important}.pr-md-3{padding-right:16px !important}.pb-md-3{padding-bottom:16px !important}.pl-md-3{padding-left:16px !important}.py-md-3{padding-top:16px !important;padding-bottom:16px !important}.p-md-4{padding:24px !important}.pt-md-4{padding-top:24px !important}.pr-md-4{padding-right:24px !important}.pb-md-4{padding-bottom:24px !important}.pl-md-4{padding-left:24px !important}.py-md-4{padding-top:24px !important;padding-bottom:24px !important}.p-md-5{padding:32px !important}.pt-md-5{padding-top:32px !important}.pr-md-5{padding-right:32px !important}.pb-md-5{padding-bottom:32px !important}.pl-md-5{padding-left:32px !important}.py-md-5{padding-top:32px !important;padding-bottom:32px !important}.p-md-6{padding:40px !important}.pt-md-6{padding-top:40px !important}.pr-md-6{padding-right:40px !important}.pb-md-6{padding-bottom:40px !important}.pl-md-6{padding-left:40px !important}.py-md-6{padding-top:40px !important;padding-bottom:40px !important}.p-md-7{padding:48px !important}.pt-md-7{padding-top:48px !important}.pr-md-7{padding-right:48px !important}.pb-md-7{padding-bottom:48px !important}.pl-md-7{padding-left:48px !important}.py-md-7{padding-top:48px !important;padding-bottom:48px !important}.p-md-8{padding:64px !important}.pt-md-8{padding-top:64px !important}.pr-md-8{padding-right:64px !important}.pb-md-8{padding-bottom:64px !important}.pl-md-8{padding-left:64px !important}.py-md-8{padding-top:64px !important;padding-bottom:64px !important}.p-md-9{padding:80px !important}.pt-md-9{padding-top:80px !important}.pr-md-9{padding-right:80px !important}.pb-md-9{padding-bottom:80px !important}.pl-md-9{padding-left:80px !important}.py-md-9{padding-top:80px !important;padding-bottom:80px !important}.p-md-10{padding:96px !important}.pt-md-10{padding-top:96px !important}.pr-md-10{padding-right:96px !important}.pb-md-10{padding-bottom:96px !important}.pl-md-10{padding-left:96px !important}.py-md-10{padding-top:96px !important;padding-bottom:96px !important}.p-md-11{padding:112px !important}.pt-md-11{padding-top:112px !important}.pr-md-11{padding-right:112px !important}.pb-md-11{padding-bottom:112px !important}.pl-md-11{padding-left:112px !important}.py-md-11{padding-top:112px !important;padding-bottom:112px !important}.p-md-12{padding:128px !important}.pt-md-12{padding-top:128px !important}.pr-md-12{padding-right:128px !important}.pb-md-12{padding-bottom:128px !important}.pl-md-12{padding-left:128px !important}.py-md-12{padding-top:128px !important;padding-bottom:128px !important}}@media (min-width: 1012px){.p-lg-0{padding:0 !important}.pt-lg-0{padding-top:0 !important}.pr-lg-0{padding-right:0 !important}.pb-lg-0{padding-bottom:0 !important}.pl-lg-0{padding-left:0 !important}.py-lg-0{padding-top:0 !important;padding-bottom:0 !important}.p-lg-1{padding:4px !important}.pt-lg-1{padding-top:4px !important}.pr-lg-1{padding-right:4px !important}.pb-lg-1{padding-bottom:4px !important}.pl-lg-1{padding-left:4px !important}.py-lg-1{padding-top:4px !important;padding-bottom:4px !important}.p-lg-2{padding:8px !important}.pt-lg-2{padding-top:8px !important}.pr-lg-2{padding-right:8px !important}.pb-lg-2{padding-bottom:8px !important}.pl-lg-2{padding-left:8px !important}.py-lg-2{padding-top:8px !important;padding-bottom:8px !important}.p-lg-3{padding:16px !important}.pt-lg-3{padding-top:16px !important}.pr-lg-3{padding-right:16px !important}.pb-lg-3{padding-bottom:16px !important}.pl-lg-3{padding-left:16px !important}.py-lg-3{padding-top:16px !important;padding-bottom:16px !important}.p-lg-4{padding:24px !important}.pt-lg-4{padding-top:24px !important}.pr-lg-4{padding-right:24px !important}.pb-lg-4{padding-bottom:24px !important}.pl-lg-4{padding-left:24px !important}.py-lg-4{padding-top:24px !important;padding-bottom:24px !important}.p-lg-5{padding:32px !important}.pt-lg-5{padding-top:32px !important}.pr-lg-5{padding-right:32px !important}.pb-lg-5{padding-bottom:32px !important}.pl-lg-5{padding-left:32px !important}.py-lg-5{padding-top:32px !important;padding-bottom:32px !important}.p-lg-6{padding:40px !important}.pt-lg-6{padding-top:40px !important}.pr-lg-6{padding-right:40px !important}.pb-lg-6{padding-bottom:40px !important}.pl-lg-6{padding-left:40px !important}.py-lg-6{padding-top:40px !important;padding-bottom:40px !important}.p-lg-7{padding:48px !important}.pt-lg-7{padding-top:48px !important}.pr-lg-7{padding-right:48px !important}.pb-lg-7{padding-bottom:48px !important}.pl-lg-7{padding-left:48px !important}.py-lg-7{padding-top:48px !important;padding-bottom:48px !important}.p-lg-8{padding:64px !important}.pt-lg-8{padding-top:64px !important}.pr-lg-8{padding-right:64px !important}.pb-lg-8{padding-bottom:64px !important}.pl-lg-8{padding-left:64px !important}.py-lg-8{padding-top:64px !important;padding-bottom:64px !important}.p-lg-9{padding:80px !important}.pt-lg-9{padding-top:80px !important}.pr-lg-9{padding-right:80px !important}.pb-lg-9{padding-bottom:80px !important}.pl-lg-9{padding-left:80px !important}.py-lg-9{padding-top:80px !important;padding-bottom:80px !important}.p-lg-10{padding:96px !important}.pt-lg-10{padding-top:96px !important}.pr-lg-10{padding-right:96px !important}.pb-lg-10{padding-bottom:96px !important}.pl-lg-10{padding-left:96px !important}.py-lg-10{padding-top:96px !important;padding-bottom:96px !important}.p-lg-11{padding:112px !important}.pt-lg-11{padding-top:112px !important}.pr-lg-11{padding-right:112px !important}.pb-lg-11{padding-bottom:112px !important}.pl-lg-11{padding-left:112px !important}.py-lg-11{padding-top:112px !important;padding-bottom:112px !important}.p-lg-12{padding:128px !important}.pt-lg-12{padding-top:128px !important}.pr-lg-12{padding-right:128px !important}.pb-lg-12{padding-bottom:128px !important}.pl-lg-12{padding-left:128px !important}.py-lg-12{padding-top:128px !important;padding-bottom:128px !important}}@media (min-width: 1280px){.p-xl-0{padding:0 !important}.pt-xl-0{padding-top:0 !important}.pr-xl-0{padding-right:0 !important}.pb-xl-0{padding-bottom:0 !important}.pl-xl-0{padding-left:0 !important}.py-xl-0{padding-top:0 !important;padding-bottom:0 !important}.p-xl-1{padding:4px !important}.pt-xl-1{padding-top:4px !important}.pr-xl-1{padding-right:4px !important}.pb-xl-1{padding-bottom:4px !important}.pl-xl-1{padding-left:4px !important}.py-xl-1{padding-top:4px !important;padding-bottom:4px !important}.p-xl-2{padding:8px !important}.pt-xl-2{padding-top:8px !important}.pr-xl-2{padding-right:8px !important}.pb-xl-2{padding-bottom:8px !important}.pl-xl-2{padding-left:8px !important}.py-xl-2{padding-top:8px !important;padding-bottom:8px !important}.p-xl-3{padding:16px !important}.pt-xl-3{padding-top:16px !important}.pr-xl-3{padding-right:16px !important}.pb-xl-3{padding-bottom:16px !important}.pl-xl-3{padding-left:16px !important}.py-xl-3{padding-top:16px !important;padding-bottom:16px !important}.p-xl-4{padding:24px !important}.pt-xl-4{padding-top:24px !important}.pr-xl-4{padding-right:24px !important}.pb-xl-4{padding-bottom:24px !important}.pl-xl-4{padding-left:24px !important}.py-xl-4{padding-top:24px !important;padding-bottom:24px !important}.p-xl-5{padding:32px !important}.pt-xl-5{padding-top:32px !important}.pr-xl-5{padding-right:32px !important}.pb-xl-5{padding-bottom:32px !important}.pl-xl-5{padding-left:32px !important}.py-xl-5{padding-top:32px !important;padding-bottom:32px !important}.p-xl-6{padding:40px !important}.pt-xl-6{padding-top:40px !important}.pr-xl-6{padding-right:40px !important}.pb-xl-6{padding-bottom:40px !important}.pl-xl-6{padding-left:40px !important}.py-xl-6{padding-top:40px !important;padding-bottom:40px !important}.p-xl-7{padding:48px !important}.pt-xl-7{padding-top:48px !important}.pr-xl-7{padding-right:48px !important}.pb-xl-7{padding-bottom:48px !important}.pl-xl-7{padding-left:48px !important}.py-xl-7{padding-top:48px !important;padding-bottom:48px !important}.p-xl-8{padding:64px !important}.pt-xl-8{padding-top:64px !important}.pr-xl-8{padding-right:64px !important}.pb-xl-8{padding-bottom:64px !important}.pl-xl-8{padding-left:64px !important}.py-xl-8{padding-top:64px !important;padding-bottom:64px !important}.p-xl-9{padding:80px !important}.pt-xl-9{padding-top:80px !important}.pr-xl-9{padding-right:80px !important}.pb-xl-9{padding-bottom:80px !important}.pl-xl-9{padding-left:80px !important}.py-xl-9{padding-top:80px !important;padding-bottom:80px !important}.p-xl-10{padding:96px !important}.pt-xl-10{padding-top:96px !important}.pr-xl-10{padding-right:96px !important}.pb-xl-10{padding-bottom:96px !important}.pl-xl-10{padding-left:96px !important}.py-xl-10{padding-top:96px !important;padding-bottom:96px !important}.p-xl-11{padding:112px !important}.pt-xl-11{padding-top:112px !important}.pr-xl-11{padding-right:112px !important}.pb-xl-11{padding-bottom:112px !important}.pl-xl-11{padding-left:112px !important}.py-xl-11{padding-top:112px !important;padding-bottom:112px !important}.p-xl-12{padding:128px !important}.pt-xl-12{padding-top:128px !important}.pr-xl-12{padding-right:128px !important}.pb-xl-12{padding-bottom:128px !important}.pl-xl-12{padding-left:128px !important}.py-xl-12{padding-top:128px !important;padding-bottom:128px !important}}\n\n/*# sourceMappingURL=primer.css.map */"
  },
  {
    "path": "lighthouserc.json",
    "content": "{\n  \"ci\": {\n    \"collect\": {\n      \"url\": [\"http://localhost:4000/?prefers-color-scheme=light\", \"http://localhost:4000/?prefers-color-scheme=dark\"],\n      \"startServerCommand\": \"cd docs && bundle exec jekyll serve\",\n      \"startServerReadyPattern\": \"Server running...\"\n    },\n    \"assert\": {\n      \"preset\": \"lighthouse:no-pwa\",\n      \"assertions\": {\n        \"unused-css-rules\": \"off\",\n        \"uses-text-compression\": \"off\",\n        \"render-blocking-resources\": \"off\",\n        \"uses-rel-preload\": \"off\",\n        \"first-contentful-paint\": [\"error\", {\"minScore\": 0.6}],\n        \"first-meaningful-paint\": [\"error\", {\"maxNumericValue\": 3000}],\n        \"largest-contentful-paint\": [\"error\", {\"maxNumericValue\": 3000}],\n        \"deprecations\": \"off\",\n        \"csp-xss\": \"off\"\n      }\n    },\n    \"upload\": {\n      \"target\": \"temporary-public-storage\"\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@github/catalyst\",\n  \"version\": \"1.3.0\",\n  \"description\": \"Helpers for creating HTML Elements as Controllers\",\n  \"homepage\": \"https://github.github.io/catalyst\",\n  \"bugs\": {\n    \"url\": \"https://github.com/github/catalyst/issues\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/github/catalyst.git\"\n  },\n  \"license\": \"MIT\",\n  \"author\": \"GitHub Inc.\",\n  \"contributors\": [\n    \"Keith Cirkel (https://keithcirkel.co.uk/)\",\n    \"Kristján Oddsson <koddsson@gmail.com>\"\n  ],\n  \"type\": \"module\",\n  \"main\": \"lib/index.js\",\n  \"module\": \"lib/index.js\",\n  \"files\": [\n    \"lib\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsc --build tsconfig.build.json\",\n    \"build:docs\": \"cd docs && JEKYLL_ENV=production bundle exec jekyll build\",\n    \"clean\": \"tsc --build --clean tsconfig.build.json\",\n    \"lint\": \"eslint . --ignore-path .gitignore\",\n    \"postlint\": \"tsc\",\n    \"prepack\": \"npm run build\",\n    \"presize\": \"npm run build\",\n    \"size\": \"size-limit\",\n    \"test\": \"web-test-runner\"\n  },\n  \"prettier\": \"@github/prettier-config\",\n  \"devDependencies\": {\n    \"@github/prettier-config\": \"^0.0.4\",\n    \"@lhci/cli\": \"^0.15.1\",\n    \"@open-wc/testing\": \"^4.0.0\",\n    \"@size-limit/preset-small-lib\": \"^8.0.1\",\n    \"@types/mocha\": \"^10.0.10\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.36.1\",\n    \"@typescript-eslint/parser\": \"^5.36.1\",\n    \"@web/dev-server-esbuild\": \"^0.3.2\",\n    \"@web/test-runner\": \"^0.20.0\",\n    \"eslint\": \"^8.23.0\",\n    \"eslint-plugin-github\": \"^4.3.7\",\n    \"sinon\": \"^14.0.0\",\n    \"size-limit\": \"^8.0.1\",\n    \"tslib\": \"^2.4.0\",\n    \"typescript\": \"^4.8.2\"\n  },\n  \"size-limit\": [\n    {\n      \"path\": \"lib/index.js\",\n      \"import\": \"{controller, attr, target, targets}\",\n      \"limit\": \"2.5kb\"\n    },\n    {\n      \"path\": \"lib/abilities.js\",\n      \"import\": \"{providable}\",\n      \"limit\": \"1.5kb\"\n    }\n  ]\n}\n"
  },
  {
    "path": "src/abilities.ts",
    "content": "export {provide, getProvide, consume, getConsume, providable} from './providable.js'\n"
  },
  {
    "path": "src/ability.ts",
    "content": "import type {CustomElementClass} from './custom-element.js'\n\ntype Decorator = (Class: CustomElementClass) => unknown\nconst abilityMarkers = new WeakMap<CustomElementClass, Set<Decorator>>()\nexport const createAbility = <TExtend, TClass extends CustomElementClass>(\n  decorate: (Class: TClass) => TExtend\n): ((Class: TClass) => TExtend) => {\n  return (Class: TClass): TExtend => {\n    const markers = abilityMarkers.get(Class)\n    if (markers?.has(decorate as Decorator)) return Class as unknown as TExtend\n    const NewClass = decorate(Class) as TExtend\n    Object.defineProperty(NewClass, 'name', {value: Class.name})\n    const newMarkers = new Set(markers)\n    newMarkers.add(decorate as Decorator)\n    abilityMarkers.set(NewClass as unknown as CustomElementClass, newMarkers)\n    return NewClass\n  }\n}\n"
  },
  {
    "path": "src/attr.ts",
    "content": "import type {CustomElementClass} from './custom-element.js'\nimport {mustDasherize} from './dasherize.js'\nimport {meta} from './core.js'\n\nconst attrKey = 'attr'\ntype attrValue = string | number | boolean\n\n/**\n * Attr is a decorator which tags a property as one to be initialized via\n * `initializeAttrs`.\n *\n * The signature is typed such that the property must be one of a String,\n * Number or Boolean. This matches the behavior of `initializeAttrs`.\n */\nexport function attr<K extends string>(proto: Record<K, attrValue>, key: K): void {\n  meta(proto, attrKey).add(key)\n}\n\n/**\n * initializeAttrs is called with a set of class property names (if omitted, it\n * will look for any properties tagged with the `@attr` decorator). With this\n * list it defines property descriptors for each property that map to `data-*`\n * attributes on the HTMLElement instance.\n *\n * It works around Native Class Property semantics - which are equivalent to\n * calling `Object.defineProperty` on the instance upon creation, but before\n * `constructor()` is called.\n *\n * If a class property is assigned to the class body, it will infer the type\n * (using `typeof`) and define an appropriate getter/setter combo that aligns\n * to that type. This means class properties assigned to Numbers can only ever\n * be Numbers, assigned to Booleans can only ever be Booleans, and assigned to\n * Strings can only ever be Strings.\n *\n * This is automatically called as part of `@controller`. If a class uses the\n * `@controller` decorator it should not call this manually.\n */\nconst initialized = new WeakSet<Element>()\nexport function initializeAttrs(instance: HTMLElement, names?: Iterable<string>): void {\n  if (initialized.has(instance)) return\n  initialized.add(instance)\n  const proto = Object.getPrototypeOf(instance)\n  const prefix = proto?.constructor?.attrPrefix ?? 'data-'\n  if (!names) names = meta(proto, attrKey)\n  for (const key of names) {\n    const value = (<Record<PropertyKey, unknown>>(<unknown>instance))[key]\n    const name = mustDasherize(`${prefix}${key}`)\n    let descriptor: PropertyDescriptor = {\n      configurable: true,\n      get(this: HTMLElement): string {\n        return this.getAttribute(name) || ''\n      },\n      set(this: HTMLElement, newValue: string) {\n        this.setAttribute(name, newValue || '')\n      }\n    }\n    if (typeof value === 'number') {\n      descriptor = {\n        configurable: true,\n        get(this: HTMLElement): number {\n          return Number(this.getAttribute(name) || 0)\n        },\n        set(this: HTMLElement, newValue: string) {\n          this.setAttribute(name, newValue)\n        }\n      }\n    } else if (typeof value === 'boolean') {\n      descriptor = {\n        configurable: true,\n        get(this: HTMLElement): boolean {\n          return this.hasAttribute(name)\n        },\n        set(this: HTMLElement, newValue: boolean) {\n          this.toggleAttribute(name, newValue)\n        }\n      }\n    }\n    Object.defineProperty(instance, key, descriptor)\n    if (key in instance && !instance.hasAttribute(name)) {\n      descriptor.set!.call(instance, value)\n    }\n  }\n}\n\nexport function defineObservedAttributes(classObject: CustomElementClass): void {\n  let observed = classObject.observedAttributes || []\n\n  const prefix = classObject.attrPrefix ?? 'data-'\n  const attrToAttributeName = (name: string) => mustDasherize(`${prefix}${name}`)\n\n  Object.defineProperty(classObject, 'observedAttributes', {\n    configurable: true,\n    get() {\n      return [...meta(classObject.prototype, attrKey)].map(attrToAttributeName).concat(observed)\n    },\n    set(attributes: string[]) {\n      observed = attributes\n    }\n  })\n}\n"
  },
  {
    "path": "src/auto-shadow-root.ts",
    "content": "export function autoShadowRoot(element: HTMLElement): void {\n  for (const template of element.querySelectorAll<HTMLTemplateElement>('template[data-shadowroot]')) {\n    if (template.parentElement === element) {\n      element\n        .attachShadow({\n          mode: template.getAttribute('data-shadowroot') === 'closed' ? 'closed' : 'open'\n        })\n        .append(template.content.cloneNode(true))\n    }\n  }\n}\n"
  },
  {
    "path": "src/bind.ts",
    "content": "const controllers = new WeakSet<Element>()\n\n/*\n * Bind `[data-action]` elements from the DOM to their actions.\n *\n */\nexport function bind(controller: HTMLElement): void {\n  controllers.add(controller)\n  if (controller.shadowRoot) bindShadow(controller.shadowRoot)\n  bindElements(controller)\n  listenForBind(controller.ownerDocument)\n}\n\nexport function bindShadow(root: ShadowRoot): void {\n  bindElements(root)\n  listenForBind(root)\n}\n\nconst observers = new WeakMap<Node, Subscription>()\n/**\n * Set up observer that will make sure any actions that are dynamically\n * injected into `el` will be bound to it's controller.\n *\n * This returns a Subscription object which you can call `unsubscribe()` on to\n * stop further live updates.\n */\nexport function listenForBind(el: Node = document): Subscription {\n  if (observers.has(el)) return observers.get(el)!\n  let closed = false\n  const observer = new MutationObserver(mutations => {\n    for (const mutation of mutations) {\n      if (mutation.type === 'attributes' && mutation.target instanceof Element) {\n        bindActions(mutation.target)\n      } else if (mutation.type === 'childList' && mutation.addedNodes.length) {\n        for (const node of mutation.addedNodes) {\n          if (node instanceof Element) {\n            bindElements(node)\n          }\n        }\n      }\n    }\n  })\n  observer.observe(el, {childList: true, subtree: true, attributeFilter: ['data-action']})\n  const subscription = {\n    get closed() {\n      return closed\n    },\n    unsubscribe() {\n      closed = true\n      observers.delete(el)\n      observer.disconnect()\n    }\n  }\n  observers.set(el, subscription)\n  return subscription\n}\n\ninterface Subscription {\n  closed: boolean\n  unsubscribe(): void\n}\n\nfunction bindElements(root: Element | ShadowRoot) {\n  for (const el of root.querySelectorAll('[data-action]')) {\n    bindActions(el)\n  }\n  // Also bind the controller to itself\n  if (root instanceof Element && root.hasAttribute('data-action')) {\n    bindActions(root)\n  }\n}\n\n// Bind a single function to all events to avoid anonymous closure performance penalty.\nfunction handleEvent(event: Event) {\n  const el = event.currentTarget as Element\n  for (const binding of bindings(el)) {\n    if (event.type === binding.type) {\n      type EventDispatcher = HTMLElement & Record<string, (ev: Event) => unknown>\n      const controller = el.closest<EventDispatcher>(binding.tag)!\n      if (controllers.has(controller) && typeof controller[binding.method] === 'function') {\n        controller[binding.method](event)\n      }\n      const root = el.getRootNode()\n      if (root instanceof ShadowRoot && controllers.has(root.host) && root.host.matches(binding.tag)) {\n        const shadowController = root.host as EventDispatcher\n        if (typeof shadowController[binding.method] === 'function') {\n          shadowController[binding.method](event)\n        }\n      }\n    }\n  }\n}\n\ntype Binding = {type: string; tag: string; method: string}\nfunction* bindings(el: Element): Iterable<Binding> {\n  for (const action of (el.getAttribute('data-action') || '').trim().split(/\\s+/)) {\n    const eventSep = action.lastIndexOf(':')\n    const methodSep = Math.max(0, action.lastIndexOf('#')) || action.length\n    yield {\n      type: action.slice(0, eventSep),\n      tag: action.slice(eventSep + 1, methodSep),\n      method: action.slice(methodSep + 1) || 'handleEvent'\n    } || 'handleEvent'\n  }\n}\n\nfunction bindActions(el: Element) {\n  for (const binding of bindings(el)) {\n    el.addEventListener(binding.type, handleEvent)\n  }\n}\n"
  },
  {
    "path": "src/controllable.ts",
    "content": "import type {CustomElementClass, CustomElement} from './custom-element.js'\nimport {createAbility} from './ability.js'\n\nexport interface Controllable {\n  [attachShadowCallback]?(shadowRoot: ShadowRoot): void\n  [attachInternalsCallback]?(internals: ElementInternals): void\n}\nexport interface ControllableClass {\n  // TS mandates Constructors that get mixins have `...args: any[]`\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  new (...args: any[]): Controllable\n}\n\nexport const attachShadowCallback = Symbol()\nexport const attachInternalsCallback = Symbol()\n\nconst shadows = new WeakMap<Controllable, ShadowRoot | undefined>()\nconst internals = new WeakMap<Controllable, ElementInternals>()\nconst internalsCalled = new WeakSet()\nexport const controllable = createAbility(\n  <T extends CustomElementClass>(Class: T): T & ControllableClass =>\n    class extends Class {\n      // TS mandates Constructors that get mixins have `...args: any[]`\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      constructor(...args: any[]) {\n        super(...args)\n        const shadowRoot = this.shadowRoot\n        if (shadowRoot && shadowRoot !== shadows.get(this)) this[attachShadowCallback](shadowRoot)\n        if (!internalsCalled.has(this)) {\n          try {\n            this.attachInternals()\n          } catch {\n            // Ignore errors\n          }\n        }\n      }\n\n      connectedCallback() {\n        this.setAttribute('data-catalyst', '')\n        super.connectedCallback?.()\n      }\n\n      attachShadow(...args: [init: ShadowRootInit]): ShadowRoot {\n        const shadowRoot = super.attachShadow(...args)\n        this[attachShadowCallback](shadowRoot)\n        return shadowRoot\n      }\n\n      [attachShadowCallback](this: CustomElement & Controllable, shadowRoot: ShadowRoot) {\n        shadows.set(this, shadowRoot)\n      }\n\n      attachInternals(): ElementInternals {\n        if (internals.has(this) && !internalsCalled.has(this)) {\n          internalsCalled.add(this)\n          return internals.get(this)!\n        }\n        const elementInternals = super.attachInternals()\n        this[attachInternalsCallback](elementInternals)\n        internals.set(this, elementInternals)\n        return elementInternals\n      }\n\n      [attachInternalsCallback](elementInternals: ElementInternals) {\n        const shadowRoot = elementInternals.shadowRoot\n        if (shadowRoot && shadowRoot !== shadows.get(this)) {\n          this[attachShadowCallback](shadowRoot)\n        }\n      }\n    }\n)\n"
  },
  {
    "path": "src/controller.ts",
    "content": "import {CatalystDelegate} from './core.js'\nimport type {CustomElementClass} from './custom-element.js'\n/**\n * Controller is a decorator to be used over a class that extends HTMLElement.\n * It will automatically `register()` the component in the customElement\n * registry, as well as ensuring `bind(this)` is called on `connectedCallback`,\n * wrapping the classes `connectedCallback` method if needed.\n */\nexport function controller(classObject: CustomElementClass): void\nexport function controller(name: string): (classObject: CustomElementClass) => void\nexport function controller(\n  classObjectOrName: CustomElementClass | string\n): void | ((classObject: CustomElementClass) => void) {\n  if (typeof classObjectOrName === 'string') {\n    return (classObject: CustomElementClass) => {\n      new CatalystDelegate(classObject, classObjectOrName)\n    }\n  }\n  new CatalystDelegate(classObjectOrName)\n}\n"
  },
  {
    "path": "src/core.ts",
    "content": "import {register} from './register.js'\nimport {bind, bindShadow} from './bind.js'\nimport {autoShadowRoot} from './auto-shadow-root.js'\nimport {defineObservedAttributes, initializeAttrs} from './attr.js'\nimport type {CustomElementClass} from './custom-element.js'\nimport {observe} from './lazy-define.js'\n\nconst symbol = Symbol.for('catalyst')\n\nexport class CatalystDelegate {\n  constructor(classObject: CustomElementClass, elementName?: string) {\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\n    const delegate = this\n\n    const connectedCallback = classObject.prototype.connectedCallback\n    classObject.prototype.connectedCallback = function (this: HTMLElement) {\n      delegate.connectedCallback(this, connectedCallback)\n    }\n\n    const disconnectedCallback = classObject.prototype.disconnectedCallback\n    classObject.prototype.disconnectedCallback = function (this: HTMLElement) {\n      delegate.disconnectedCallback(this, disconnectedCallback)\n    }\n\n    const attributeChangedCallback = classObject.prototype.attributeChangedCallback\n    classObject.prototype.attributeChangedCallback = function (\n      this: HTMLElement,\n      name: string,\n      oldValue: string | null,\n      newValue: string | null\n    ) {\n      delegate.attributeChangedCallback(this, name, oldValue, newValue, attributeChangedCallback)\n    }\n\n    let observedAttributes = classObject.observedAttributes || []\n    Object.defineProperty(classObject, 'observedAttributes', {\n      configurable: true,\n      get() {\n        return delegate.observedAttributes(this, observedAttributes)\n      },\n      set(attributes: string[]) {\n        observedAttributes = attributes\n      }\n    })\n\n    defineObservedAttributes(classObject)\n    register(classObject, elementName)\n  }\n\n  observedAttributes(instance: HTMLElement, observedAttributes: string[]) {\n    return observedAttributes\n  }\n\n  connectedCallback(instance: HTMLElement, connectedCallback: () => void) {\n    instance.toggleAttribute('data-catalyst', true)\n    customElements.upgrade(instance)\n    autoShadowRoot(instance)\n    initializeAttrs(instance)\n    bind(instance)\n    connectedCallback?.call(instance)\n    if (instance.shadowRoot) {\n      bindShadow(instance.shadowRoot)\n      observe(instance.shadowRoot)\n    }\n  }\n\n  disconnectedCallback(element: HTMLElement, disconnectedCallback: () => void) {\n    disconnectedCallback?.call(element)\n  }\n\n  attributeChangedCallback(\n    instance: HTMLElement,\n    name: string,\n    oldValue: string | null,\n    newValue: string | null,\n    attributeChangedCallback: (...args: unknown[]) => void\n  ) {\n    initializeAttrs(instance)\n    if (name !== 'data-catalyst' && attributeChangedCallback) {\n      attributeChangedCallback.call(instance, name, oldValue, newValue)\n    }\n  }\n}\n\nexport function meta(proto: Record<PropertyKey, unknown>, name: string): Set<string> {\n  if (!Object.prototype.hasOwnProperty.call(proto, symbol)) {\n    const parent = proto[symbol] as Map<string, Set<string>> | undefined\n    const map = (proto[symbol] = new Map<string, Set<string>>())\n    if (parent) {\n      for (const [key, value] of parent) {\n        map.set(key, new Set(value))\n      }\n    }\n  }\n  const map = proto[symbol] as Map<string, Set<string>>\n  if (!map.has(name)) map.set(name, new Set<string>())\n  return map.get(name)!\n}\n"
  },
  {
    "path": "src/custom-element.ts",
    "content": "export interface CustomElement extends HTMLElement {\n  connectedCallback?(): void\n  attributeChangedCallback?(name: string, oldValue: string | null, newValue: string | null): void\n  disconnectedCallback?(): void\n  adoptedCallback?(): void\n  formAssociatedCallback?(form: HTMLFormElement): void\n  formDisabledCallback?(disabled: boolean): void\n  formResetCallback?(): void\n  formStateRestoreCallback?(state: unknown, reason: 'autocomplete' | 'restore'): void\n}\n\nexport interface CustomElementClass {\n  // TS mandates Constructors that get mixins have `...args: any[]`\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  new (...args: any[]): CustomElement\n  observedAttributes?: string[]\n  disabledFeatures?: string[]\n  formAssociated?: boolean\n\n  attrPrefix?: string\n}\n"
  },
  {
    "path": "src/dasherize.ts",
    "content": "export const dasherize = (str: unknown): string =>\n  String(typeof str === 'symbol' ? str.description : str)\n    .replace(/([A-Z]($|[a-z]))/g, '-$1')\n    .replace(/--/g, '-')\n    .replace(/^-|-$/, '')\n    .toLowerCase()\n\nexport const mustDasherize = (str: unknown, type = 'property'): string => {\n  const dashed = dasherize(str)\n  if (!dashed.includes('-')) {\n    throw new DOMException(`${type}: ${String(str)} is not a valid ${type} name`, 'SyntaxError')\n  }\n  return dashed\n}\n"
  },
  {
    "path": "src/findtarget.ts",
    "content": "/**\n * findTarget will run `querySelectorAll` against the given controller, plus\n * its shadowRoot, returning any the first child that:\n *\n *  - Matches the selector of `[data-target~=\"tag.name\"]` where tag is the\n *  tagName of the given HTMLElement, and `name` is the given `name` argument.\n *\n *  - Closest ascendant of the element, that matches the tagname of the\n *  controller, is the specific instance of the controller itself - in other\n *  words it is not nested in other controllers of the same type.\n *\n */\nexport function findTarget(controller: HTMLElement, name: string): Element | undefined {\n  const tag = controller.tagName.toLowerCase()\n  if (controller.shadowRoot) {\n    for (const el of controller.shadowRoot.querySelectorAll(`[data-target~=\"${tag}.${name}\"]`)) {\n      if (!el.closest(tag)) return el\n    }\n  }\n  for (const el of controller.querySelectorAll(`[data-target~=\"${tag}.${name}\"]`)) {\n    if (el.closest(tag) === controller) return el\n  }\n}\n\nexport function findTargets(controller: HTMLElement, name: string): Element[] {\n  const tag = controller.tagName.toLowerCase()\n  const targets = []\n  if (controller.shadowRoot) {\n    for (const el of controller.shadowRoot.querySelectorAll(`[data-targets~=\"${tag}.${name}\"]`)) {\n      if (!el.closest(tag)) targets.push(el)\n    }\n  }\n  for (const el of controller.querySelectorAll(`[data-targets~=\"${tag}.${name}\"]`)) {\n    if (el.closest(tag) === controller) targets.push(el)\n  }\n  return targets\n}\n"
  },
  {
    "path": "src/get-property-descriptor.ts",
    "content": "export const getPropertyDescriptor = (instance: unknown, key: PropertyKey): PropertyDescriptor | undefined => {\n  while (instance) {\n    const descriptor = Object.getOwnPropertyDescriptor(instance, key)\n    if (descriptor) return descriptor\n    instance = Object.getPrototypeOf(instance)\n  }\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "export {bind, listenForBind} from './bind.js'\nexport {register} from './register.js'\nexport {findTarget, findTargets} from './findtarget.js'\nexport {target, targets} from './target.js'\nexport {controller} from './controller.js'\nexport {attr, initializeAttrs, defineObservedAttributes} from './attr.js'\nexport {autoShadowRoot} from './auto-shadow-root.js'\nexport {lazyDefine} from './lazy-define.js'\n"
  },
  {
    "path": "src/lazy-define.ts",
    "content": "type Strategy = (tagName: string) => Promise<void>\n\nconst dynamicElements = new Map<string, Set<() => void>>()\n\nconst ready = new Promise<void>(resolve => {\n  if (document.readyState !== 'loading') {\n    resolve()\n  } else {\n    document.addEventListener('readystatechange', () => resolve(), {once: true})\n  }\n})\n\nconst firstInteraction = new Promise<void>(resolve => {\n  const controller = new AbortController()\n  controller.signal.addEventListener('abort', () => resolve())\n  const listenerOptions = {once: true, passive: true, signal: controller.signal}\n  const handler = () => controller.abort()\n\n  document.addEventListener('mousedown', handler, listenerOptions)\n  // eslint-disable-next-line github/require-passive-events\n  document.addEventListener('touchstart', handler, listenerOptions)\n  document.addEventListener('keydown', handler, listenerOptions)\n  document.addEventListener('pointerdown', handler, listenerOptions)\n})\n\nconst visible = (tagName: string): Promise<void> =>\n  new Promise<void>(resolve => {\n    const observer = new IntersectionObserver(\n      entries => {\n        for (const entry of entries) {\n          if (entry.isIntersecting) {\n            resolve()\n            observer.disconnect()\n            return\n          }\n        }\n      },\n      {\n        // Currently the threshold is set to 256px from the bottom of the viewport\n        // with a threshold of 0.1. This means the element will not load until about\n        // 2 keyboard-down-arrow presses away from being visible in the viewport,\n        // giving us some time to fetch it before the contents are made visible\n        rootMargin: '0px 0px 256px 0px',\n        threshold: 0.01\n      }\n    )\n    for (const el of document.querySelectorAll(tagName)) {\n      observer.observe(el)\n    }\n  })\n\nconst strategies: Record<string, Strategy> = {\n  ready: () => ready,\n  firstInteraction: () => firstInteraction,\n  visible\n}\n\ntype ElementLike = Element | Document | ShadowRoot\n\nconst pendingElements = new Set<ElementLike>()\nlet scanTimer: number | null = null\n\nfunction scan(element: ElementLike) {\n  pendingElements.add(element)\n  if (scanTimer != null) return\n  scanTimer = requestAnimationFrame(() => {\n    scanTimer = null\n    const elements = new Set(pendingElements)\n    pendingElements.clear()\n    if (!dynamicElements.size) {\n      return\n    }\n    outer: for (const el of elements) {\n      for (const tagName of dynamicElements.keys()) {\n        const child: Element | null = el instanceof Element && el.matches(tagName) ? el : el.querySelector(tagName)\n        if (customElements.get(tagName) || child) {\n          const strategyName = (child?.getAttribute('data-load-on') || 'ready') as keyof typeof strategies\n          const strategy = strategyName in strategies ? strategies[strategyName] : strategies.ready\n          // eslint-disable-next-line github/no-then\n          for (const cb of dynamicElements.get(tagName) || []) strategy(tagName).then(cb)\n          dynamicElements.delete(tagName)\n          if (!dynamicElements.size) break outer\n        }\n      }\n    }\n  })\n}\n\nlet elementLoader: MutationObserver\n\nexport function lazyDefine(object: Record<string, () => void>): void\nexport function lazyDefine(tagName: string, callback: () => void): void\nexport function lazyDefine(tagNameOrObj: string | Record<string, () => void>, singleCallback?: () => void) {\n  if (typeof tagNameOrObj === 'string' && singleCallback) {\n    tagNameOrObj = {[tagNameOrObj]: singleCallback}\n  }\n  for (const [tagName, callback] of Object.entries(tagNameOrObj)) {\n    if (!dynamicElements.has(tagName)) dynamicElements.set(tagName, new Set<() => void>())\n    dynamicElements.get(tagName)!.add(callback)\n  }\n  observe(document)\n}\n\nexport function observe(target: ElementLike): void {\n  elementLoader ||= new MutationObserver(mutations => {\n    if (!dynamicElements.size) return\n    for (const mutation of mutations) {\n      for (const node of mutation.addedNodes) {\n        if (node instanceof Element) scan(node)\n      }\n    }\n  })\n\n  scan(target)\n\n  elementLoader.observe(target, {subtree: true, childList: true})\n}\n"
  },
  {
    "path": "src/mark.ts",
    "content": "import {getPropertyDescriptor} from './get-property-descriptor.js'\n\ntype PropertyType = 'field' | 'getter' | 'setter' | 'method'\nexport interface PropertyDecorator {\n  (proto: object, key: PropertyKey, descriptor?: PropertyDescriptor): void\n  readonly static: unique symbol\n}\ntype GetMarks<T> = (instance: T) => Set<PropertyKey>\ntype InitializeMarks<T> = (instance: T) => void\n\ntype Context = {\n  kind: PropertyType\n  name: PropertyKey\n  access: PropertyDescriptor\n}\n\nconst getType = (descriptor?: PropertyDescriptor): PropertyType => {\n  if (descriptor) {\n    if (typeof descriptor.value === 'function') return 'method'\n    if (typeof descriptor.get === 'function') return 'getter'\n    if (typeof descriptor.set === 'function') return 'setter'\n  }\n  return 'field'\n}\n\nexport function createMark<T extends object>(\n  validate: (context: {name: PropertyKey; kind: PropertyType}) => void,\n  initialize: (instance: T, context: Context) => PropertyDescriptor | void\n): [PropertyDecorator, GetMarks<T>, InitializeMarks<T>] {\n  const marks = new WeakMap<object, Set<PropertyKey>>()\n  const get = (proto: object): Set<PropertyKey> => {\n    if (!marks.has(proto)) {\n      const parent = Object.getPrototypeOf(proto)\n      marks.set(proto, new Set(parent ? get(parent) || [] : []))\n    }\n    return marks.get(proto)!\n  }\n  const marker = (proto: object, name: PropertyKey, descriptor?: PropertyDescriptor): void => {\n    if (get(proto).has(name)) return\n    validate({name, kind: getType(descriptor)})\n    get(proto).add(name)\n  }\n  marker.static = Symbol()\n  const getMarks = (instance: T): Set<PropertyKey> => {\n    const proto = Object.getPrototypeOf(instance)\n    for (const key of proto.constructor[marker.static] || []) {\n      marker(proto, key, Object.getOwnPropertyDescriptor(proto, key))\n    }\n    return new Set(get(proto))\n  }\n  return [\n    marker as PropertyDecorator,\n    getMarks,\n    (instance: T): void => {\n      for (const name of getMarks(instance)) {\n        const access: PropertyDescriptor = getPropertyDescriptor(instance, name) || {\n          value: void 0,\n          configurable: true,\n          writable: true,\n          enumerable: true\n        }\n        const newDescriptor = initialize(instance, {name, kind: getType(access), access}) || access\n        Object.defineProperty(instance, name, Object.assign({configurable: true, enumerable: true}, newDescriptor))\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "src/providable.ts",
    "content": "import type {CustomElementClass, CustomElement} from './custom-element.js'\nimport {createMark} from './mark.js'\nimport {createAbility} from './ability.js'\n\nexport interface Context<T> {\n  name: PropertyKey\n  initialValue?: T\n}\nexport type ContextCallback<ValueType> = (value: ValueType, dispose?: () => void) => void\nexport type ContextType<T extends Context<unknown>> = T extends Context<infer Y> ? Y : never\n\nexport class ContextEvent<T extends Context<unknown>> extends Event {\n  public constructor(\n    public readonly context: T,\n    public readonly callback: ContextCallback<ContextType<T>>,\n    public readonly multiple?: boolean\n  ) {\n    super('context-request', {bubbles: true, composed: true})\n  }\n}\n\nfunction isContextEvent(event: unknown): event is ContextEvent<Context<unknown>> {\n  return (\n    event instanceof Event &&\n    event.type === 'context-request' &&\n    'context' in event &&\n    'callback' in event &&\n    'multiple' in event\n  )\n}\n\nconst contexts = new WeakMap<CustomElement, Map<PropertyKey, Set<(value: unknown) => void>>>()\nconst [provide, getProvide, initProvide] = createMark<CustomElement>(\n  ({name, kind}) => {\n    if (kind === 'setter') throw new Error(`@provide cannot decorate setter ${String(name)}`)\n    if (kind === 'method') throw new Error(`@provide cannot decorate method ${String(name)}`)\n  },\n  (instance: CustomElement, {name, kind, access}) => {\n    return {\n      get: () => (kind === 'getter' ? access.get!.call(instance) : access.value),\n      set: (newValue: unknown) => {\n        access.set?.call(instance, newValue)\n        for (const callback of contexts.get(instance)?.get(name) || []) callback(newValue)\n      }\n    }\n  }\n)\nconst [provideAsync, getProvideAsync, initProvideAsync] = createMark<CustomElement>(\n  ({name, kind}) => {\n    if (kind === 'setter') throw new Error(`@provide cannot decorate setter ${String(name)}`)\n    if (kind === 'method') throw new Error(`@provide cannot decorate method ${String(name)}`)\n  },\n  (instance: CustomElement, {name, kind, access}) => {\n    return {\n      get: () => (kind === 'getter' ? access.get!.call(instance) : access.value),\n      set: (newValue: unknown) => {\n        access.set?.call(instance, newValue)\n        for (const callback of contexts.get(instance)?.get(name) || []) callback(newValue)\n      }\n    }\n  }\n)\nconst [consume, getConsume, initConsume] = createMark<CustomElement>(\n  ({name, kind}) => {\n    if (kind === 'method') throw new Error(`@consume cannot decorate method ${String(name)}`)\n  },\n  (instance: CustomElement, {name, access}) => {\n    const initialValue: unknown = access.get?.call(instance) ?? access.value\n    let currentValue = initialValue\n    instance.dispatchEvent(\n      new ContextEvent(\n        {name, initialValue},\n        (value: unknown, dispose?: () => void) => {\n          if (!disposes.has(instance)) disposes.set(instance, new Map())\n          const instanceDisposes = disposes.get(instance)!\n          if (instanceDisposes.has(name)) {\n            const oldDispose = instanceDisposes.get(name)!\n            if (oldDispose !== dispose) oldDispose()\n          }\n          if (dispose) instanceDisposes.set(name, dispose)\n          currentValue = value\n          access.set?.call(instance, currentValue)\n        },\n        true\n      )\n    )\n    return {get: () => currentValue}\n  }\n)\n\nconst disposes = new WeakMap<CustomElement, Map<PropertyKey, () => void>>()\n\nexport {consume, provide, provideAsync, getProvide, getProvideAsync, getConsume}\nexport const providable = createAbility(\n  <T extends CustomElementClass>(Class: T): T =>\n    class extends Class {\n      [key: PropertyKey]: unknown\n\n      // TS mandates Constructors that get mixins have `...args: any[]`\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      constructor(...args: any[]) {\n        super(...args)\n        initProvide(this)\n        initProvideAsync(this)\n        const provides = getProvide(this)\n        const providesAsync = getProvideAsync(this)\n        if (provides.size || providesAsync.size) {\n          if (!contexts.has(this)) contexts.set(this, new Map())\n          const instanceContexts = contexts.get(this)!\n          this.addEventListener('context-request', event => {\n            if (!isContextEvent(event)) return\n            const name = event.context.name\n            if (!provides.has(name) && !providesAsync.has(name)) return\n            const value = this[name]\n            const dispose = () => instanceContexts.get(name)?.delete(callback)\n            const eventCallback = event.callback\n            let callback = (newValue: unknown) => eventCallback(newValue, dispose)\n            if (providesAsync.has(name)) {\n              callback = async (newValue: unknown) => eventCallback(await newValue, dispose)\n            }\n            if (event.multiple) {\n              if (!instanceContexts.has(name)) instanceContexts.set(name, new Set())\n              instanceContexts.get(name)!.add(callback)\n            }\n            event.stopPropagation()\n            callback(value)\n          })\n        }\n      }\n\n      connectedCallback() {\n        initConsume(this)\n        super.connectedCallback?.()\n      }\n\n      disconnectedCallback() {\n        for (const dispose of disposes.get(this)?.values() || []) {\n          dispose()\n        }\n      }\n    }\n)\n"
  },
  {
    "path": "src/register.ts",
    "content": "import type {CustomElementClass} from './custom-element.js'\nimport {dasherize} from './dasherize.js'\n\n/**\n * Register the controller as a custom element.\n *\n * The classname is converted to a appropriate tag name.\n *\n * Example: HelloController => hello-controller\n */\nexport function register(classObject: CustomElementClass, name?: string): CustomElementClass {\n  const tagName = name || dasherize(classObject.name).replace(/-element$/, '')\n\n  try {\n    window.customElements.define(tagName, classObject)\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n    // @ts-ignore\n    window[classObject.name] = customElements.get(tagName)\n  } catch (e: unknown) {\n    // The only reason for window.customElements.define to throw a `NotSupportedError`\n    // is if the element has already been defined.\n    if (!(e instanceof DOMException && e.name === 'NotSupportedError')) throw e\n  }\n  return classObject\n}\n"
  },
  {
    "path": "src/tag-observer.ts",
    "content": "type Parse = (str: string) => string[]\ntype Found = (el: Element, controller: Element | ShadowRoot, tag: string, ...parsed: string[]) => void\n\nfunction closestShadowPiercing(el: Element, tagName: string): Element | null {\n  const closest: Element | null = el.closest(tagName)\n  if (!closest) {\n    const shadow = el.getRootNode()\n    if (!(shadow instanceof ShadowRoot)) return null\n    return shadow.host.closest(tagName)\n  }\n  return closest\n}\n\nexport const parseElementTags = (el: Element, tag: string, parse: Parse) =>\n  (el.getAttribute(tag) || '')\n    .trim()\n    .split(/\\s+/g)\n    .map((tagPart: string) => parse(tagPart))\n\nconst registry = new Map<string, [Parse, Found]>()\nconst observer = new MutationObserver((mutations: MutationRecord[]) => {\n  for (const mutation of mutations) {\n    if (mutation.type === 'attributes') {\n      const tag = mutation.attributeName!\n      const el = mutation.target\n\n      if (el instanceof Element && registry.has(tag)) {\n        const [parse, found] = registry.get(tag)!\n        for (const [tagName, ...meta] of parseElementTags(el, tag, parse)) {\n          const controller = closestShadowPiercing(el, tagName)\n          if (controller) found(el, controller, tag, ...meta)\n        }\n      }\n    } else if (mutation.addedNodes.length) {\n      for (const node of mutation.addedNodes) {\n        if (node instanceof Element) observeElementForTags(node)\n      }\n    }\n  }\n})\n\nexport const registerTag = (tag: string, parse: Parse, found: Found) => {\n  if (registry.has(tag)) throw new Error('duplicate tag')\n  registry.set(tag, [parse, found])\n}\n\nexport const observeElementForTags = (root: Element | ShadowRoot) => {\n  for (const [tag, [parse, found]] of registry) {\n    for (const el of root.querySelectorAll(`[${tag}]`)) {\n      for (const [tagName, ...meta] of parseElementTags(el, tag, parse)) {\n        const controller = closestShadowPiercing(el, tagName)\n        if (controller) found(el, controller, tag, ...meta)\n      }\n    }\n    if (root instanceof Element && root.hasAttribute(tag)) {\n      for (const [tagName, ...meta] of parseElementTags(root, tag, parse)) {\n        const controller = closestShadowPiercing(root, tagName)\n        if (controller) found(root, controller, tag, ...meta)\n      }\n    }\n  }\n  observer.observe(root instanceof Element ? root.ownerDocument : root, {\n    childList: true,\n    subtree: true,\n    attributeFilter: Array.from(registry.keys())\n  })\n}\n"
  },
  {
    "path": "src/target.ts",
    "content": "import {findTarget, findTargets} from './findtarget.js'\nimport {meta} from './core.js'\n\n/**\n * Target is a decorator which - when assigned to a property field on the\n * class - will override that class field, turning it into a Getter which\n * returns a call to `findTarget(this, key)` where `key` is the name of the\n * property field. In other words, `@target foo` becomes a getter for\n * `findTarget(this, 'foo')`.\n */\nexport function target<K extends string>(proto: Record<K, unknown>, key: K): void {\n  meta(proto, 'target').add(key)\n  Object.defineProperty(proto, key, {\n    configurable: true,\n    get() {\n      return findTarget(this, key)\n    }\n  })\n}\n\n/**\n * Targets is a decorator which - when assigned to a property field on the\n * class - will override that class field, turning it into a Getter which\n * returns a call to `findTargets(this, key)` where `key` is the name of the\n * property field. In other words, `@targets foo` becomes a getter for\n * `findTargets(this, 'foo')`.\n */\nexport function targets<K extends string>(proto: Record<K, unknown>, key: K): void {\n  meta(proto, 'targets').add(key)\n  Object.defineProperty(proto, key, {\n    configurable: true,\n    get() {\n      return findTargets(this, key)\n    }\n  })\n}\n"
  },
  {
    "path": "test/ability.ts",
    "content": "import type {CustomElement} from '../src/custom-element.js'\nimport {expect, fixture, html} from '@open-wc/testing'\nimport {restore} from 'sinon'\nimport {createAbility} from '../src/ability.js'\n\ndescribe('ability', () => {\n  const calls: string[] = []\n  const fakeable = createAbility(\n    Class =>\n      class extends Class {\n        foo() {\n          return 'foo!'\n        }\n        connectedCallback() {\n          calls.push('fakeable connectedCallback')\n          super.connectedCallback?.()\n        }\n        disconnectedCallback() {\n          calls.push('fakeable disconnectedCallback')\n          super.disconnectedCallback?.()\n        }\n        adoptedCallback() {\n          calls.push('fakeable adoptedCallback')\n          super.adoptedCallback?.()\n        }\n        attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n          calls.push('fakeable attributeChangedCallback')\n          super.attributeChangedCallback?.(name, oldValue, newValue)\n        }\n      }\n  )\n  const otherfakeable = createAbility(\n    Class =>\n      class extends Class {\n        bar() {\n          return 'bar!'\n        }\n        connectedCallback() {\n          calls.push('otherfakeable connectedCallback')\n          super.connectedCallback?.()\n        }\n        disconnectedCallback() {\n          calls.push('otherfakeable disconnectedCallback')\n          super.disconnectedCallback?.()\n        }\n        adoptedCallback() {\n          calls.push('otherfakeable adoptedCallback')\n          super.adoptedCallback?.()\n        }\n        attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n          calls.push('otherfakeable attributeChangedCallback')\n          super.attributeChangedCallback?.(name, oldValue, newValue)\n        }\n      }\n  )\n  class Element extends HTMLElement {\n    connectedCallback() {}\n    disconnectedCallback() {}\n    adoptedCallback() {}\n    attributeChangedCallback() {}\n  }\n\n  afterEach(() => restore())\n\n  it('creates a function, which creates a subclass of the given class', async () => {\n    const DElement = fakeable(Element)\n    expect(DElement).to.have.property('prototype').instanceof(Element)\n  })\n\n  it('retains original class name', () => {\n    const DElement = fakeable(Element)\n    const D2Element = otherfakeable(Element)\n    expect(DElement).to.have.property('name', 'Element')\n    expect(D2Element).to.have.property('name', 'Element')\n  })\n\n  it('can be used in decorator position', async () => {\n    @fakeable\n    class DElement extends HTMLElement {}\n\n    expect(DElement).to.have.property('prototype').instanceof(HTMLElement)\n  })\n\n  it('can be chained with multiple abilities', async () => {\n    const DElement = fakeable(Element)\n    expect(Element).to.not.equal(DElement)\n    const D2Element = otherfakeable(DElement)\n    expect(DElement).to.not.equal(D2Element)\n    expect(DElement).to.have.property('prototype').be.instanceof(Element)\n    expect(D2Element).to.have.property('prototype').be.instanceof(Element)\n  })\n\n  it('can be called multiple times, but only applies once', async () => {\n    const MultipleFakeable = fakeable(fakeable(fakeable(fakeable(fakeable(Element)))))\n    customElements.define('multiple-fakeable', MultipleFakeable)\n    const instance: CustomElement = await fixture(html`<multiple-fakeable />`)\n    expect(calls).to.eql(['fakeable connectedCallback'])\n    instance.connectedCallback!()\n    expect(calls).to.eql(['fakeable connectedCallback', 'fakeable connectedCallback'])\n  })\n})\n"
  },
  {
    "path": "test/attr.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {controller} from '../src/controller.js'\nimport {attr} from '../src/attr.js'\n\ndescribe('Attr', () => {\n  {\n    @controller\n    class InitializeAttrTest extends HTMLElement {\n      @attr fooBar = 'hello'\n      fooBaz = 1\n\n      getCount = 0\n      setCount = 0\n      #bing = 'world'\n      get bingBaz() {\n        this.getCount += 1\n        return this.#bing\n      }\n      @attr set bingBaz(value: string) {\n        this.setCount += 1\n        this.#bing = value\n      }\n    }\n\n    let instance: InitializeAttrTest\n    beforeEach(async () => {\n      instance = await fixture(html`<initialize-attr-test />`)\n    })\n\n    it('does not error during creation', () => {\n      document.createElement('initialize-attr-test')\n    })\n\n    it('does not alter field values from their initial value', () => {\n      expect(instance).to.have.property('fooBar', 'hello')\n      expect(instance).to.have.property('fooBaz', 1)\n      expect(instance).to.have.property('bingBaz', 'world')\n    })\n\n    it('reflects the initial value as an attribute, if not present', () => {\n      expect(instance).to.have.attribute('data-foo-bar', 'hello')\n      expect(instance).to.not.have.attribute('data-foo-baz')\n      expect(instance).to.have.attribute('data-bing-baz', 'world')\n    })\n\n    it('prioritises the value in the attribute over the property', async () => {\n      instance = await fixture(html`<initialize-attr-test data-foo-bar=\"goodbye\" data-bing-baz=\"universe\" />`)\n      expect(instance).to.have.property('fooBar', 'goodbye')\n      expect(instance).to.have.attribute('data-foo-bar', 'goodbye')\n      expect(instance).to.have.property('bingBaz', 'universe')\n      expect(instance).to.have.attribute('data-bing-baz', 'universe')\n    })\n\n    it('changes the property when the attribute changes', async () => {\n      instance.setAttribute('data-foo-bar', 'goodbye')\n      await Promise.resolve()\n      expect(instance).to.have.property('fooBar', 'goodbye')\n      instance.setAttribute('data-bing-baz', 'universe')\n      await Promise.resolve()\n      expect(instance).to.have.property('bingBaz', 'universe')\n    })\n\n    it('changes the attribute when the property changes', () => {\n      instance.fooBar = 'goodbye'\n      expect(instance).to.have.attribute('data-foo-bar', 'goodbye')\n      instance.bingBaz = 'universe'\n      expect(instance).to.have.attribute('data-bing-baz', 'universe')\n    })\n  }\n\n  describe('types', () => {\n    it('infers boolean types from property and uses has/toggleAttribute', async () => {\n      @controller\n      class BooleanAttrTest extends HTMLElement {\n        @attr fooBar = false\n      }\n\n      const instance = await fixture<BooleanAttrTest>(html`<boolean-attr-test />`)\n\n      expect(instance).to.have.property('fooBar', false)\n      expect(instance).to.not.have.attribute('data-foo-bar')\n      instance.setAttribute('data-foo-bar', '7')\n      await Promise.resolve()\n      expect(instance).to.have.property('fooBar', true)\n      instance.setAttribute('data-foo-bar', 'hello')\n      await Promise.resolve()\n      expect(instance).to.have.property('fooBar', true)\n      instance.setAttribute('data-foo-bar', 'false')\n      await Promise.resolve()\n      expect(instance).to.have.property('fooBar', true)\n      instance.removeAttribute('data-foo-bar')\n      await Promise.resolve()\n      expect(instance).to.have.property('fooBar', false)\n      instance.fooBar = true\n      await Promise.resolve()\n      expect(instance).to.have.attribute('data-foo-bar', '')\n      instance.fooBar = false\n      await Promise.resolve()\n      expect(instance).to.not.have.attribute('data-foo-bar')\n      instance.removeAttribute('data-foo-bar')\n      await Promise.resolve()\n      expect(instance).to.have.property('fooBar', false)\n    })\n\n    it('avoids infinite loops', async () => {\n      @controller\n      class LoopAttrTest extends HTMLElement {\n        count = 0\n        @attr\n        get fooBar() {\n          return ++this.count\n        }\n        set fooBar(value) {\n          this.count += 1\n        }\n      }\n\n      const instance = await fixture<LoopAttrTest>(html`<loop-attr-test />`)\n\n      expect(instance).to.have.property('fooBar')\n      instance.fooBar = 1\n      instance.setAttribute('data-foo-bar', '2')\n      instance.fooBar = 3\n      instance.setAttribute('data-foo-bar', '4')\n    })\n  })\n\n  describe('naming', () => {\n    @controller\n    class NamingAttrTest extends HTMLElement {\n      @attr fooBarBazBing = 'a'\n      @attr URLBar = 'b'\n      @attr ClipX = 'c'\n    }\n\n    let instance: NamingAttrTest\n    beforeEach(async () => {\n      instance = await fixture(html`<naming-attr-test />`)\n    })\n\n    it('converts camel cased property names to their HTML dasherized equivalents', async () => {\n      expect(instance.fooBarBazBing).to.equal('a')\n      instance.fooBarBazBing = 'bar'\n      expect(instance.getAttributeNames()).to.include('data-foo-bar-baz-bing')\n    })\n\n    it('will intuitively dasherize acryonyms', async () => {\n      expect(instance.URLBar).to.equal('b')\n      instance.URLBar = 'bar'\n      expect(instance.getAttributeNames()).to.include('data-url-bar')\n    })\n\n    it('dasherizes cap suffixed names correctly', async () => {\n      expect(instance.ClipX).to.equal('c')\n      instance.ClipX = 'bar'\n      expect(instance.getAttributeNames()).to.include('data-clip-x')\n    })\n  })\n\n  describe('prefix', () => {\n    @controller\n    class PrefixAttrTest extends HTMLElement {\n      static attrPrefix = 'foo-'\n      @attr fooBarBazBing = 'a'\n      @attr URLBar = 'b'\n      @attr ClipX = 'c'\n    }\n\n    let instance: PrefixAttrTest\n    beforeEach(async () => {\n      instance = await fixture(html`<prefix-attr-test />`)\n    })\n\n    it('respects custom attrPrefix static member', async () => {\n      expect(instance.getAttributeNames()).to.include('foo-foo-bar-baz-bing')\n      expect(instance.getAttributeNames()).to.include('foo-url-bar')\n      expect(instance.getAttributeNames()).to.include('foo-clip-x')\n    })\n  })\n})\n"
  },
  {
    "path": "test/auto-shadow-root.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {replace, fake} from 'sinon'\nimport {autoShadowRoot} from '../src/auto-shadow-root.js'\n\ndescribe('autoShadowRoot', () => {\n  class ShadowRootTestElement extends HTMLElement {\n    declare shadowRoot: ShadowRoot\n  }\n  window.customElements.define('shadowroot-test-element', ShadowRootTestElement)\n\n  let instance: ShadowRootTestElement\n  beforeEach(async () => {\n    instance = await fixture(html`<shadowroot-test-element />`)\n  })\n\n  it('automatically declares shadowroot for elements with `template[data-shadowroot]` children', async () => {\n    instance = await fixture(html`<shadowroot-test-element>\n      <template data-shadowroot=\"open\">Hello World</template>\n    </shadowroot-test-element>`)\n    autoShadowRoot(instance)\n\n    expect(instance).to.have.property('shadowRoot').not.equal(null)\n    expect(instance.shadowRoot.textContent).to.equal('Hello World')\n  })\n\n  it('does not attach shadowroot without a template`data-shadowroot` child', async () => {\n    instance = await fixture(html`<shadowroot-test-element>\n      <template data-notshadowroot=\"open\">Hello</template>\n      <div data-shadowroot=\"open\">World</div>\n    </shadowroot-test-element>`)\n\n    autoShadowRoot(instance)\n\n    expect(instance).to.have.property('shadowRoot').equal(null)\n  })\n\n  it('does not attach shadowroots which are not direct children of the element', async () => {\n    instance = await fixture(html`<shadowroot-test-element>\n      <div>\n        <template data-shadowroot=\"open\">Hello World</template>\n      </div>\n    </shadowroot-test-element>`)\n\n    autoShadowRoot(instance)\n\n    expect(instance).to.have.property('shadowRoot').equal(null)\n  })\n\n  it('attaches shadowRoot nodes open by default', async () => {\n    instance = await fixture(html`<shadowroot-test-element>\n      <template data-shadowroot>Hello World</template>\n    </shadowroot-test-element>`)\n\n    autoShadowRoot(instance)\n\n    expect(instance).to.have.property('shadowRoot').not.equal(null)\n    expect(instance.shadowRoot.textContent).to.equal('Hello World')\n  })\n\n  it('attaches shadowRoot nodes closed if `data-shadowroot` is `closed`', async () => {\n    instance = await fixture(html`<shadowroot-test-element>\n      <template data-shadowroot=\"closed\">Hello World</template>\n    </shadowroot-test-element>`)\n    let shadowRoot: ShadowRoot | null = null\n    replace(\n      instance,\n      'attachShadow',\n      fake((...args) => {\n        shadowRoot = Element.prototype.attachShadow.apply(instance, args)\n        return shadowRoot\n      })\n    )\n\n    autoShadowRoot(instance)\n\n    expect(instance).to.have.property('shadowRoot').equal(null)\n    expect(instance.attachShadow).to.have.been.calledOnceWith({mode: 'closed'})\n    expect(shadowRoot!.textContent).to.equal('Hello World')\n  })\n})\n"
  },
  {
    "path": "test/bind.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {fake} from 'sinon'\nimport {controller} from '../src/controller.js'\nimport {bindShadow} from '../src/bind.js'\n\ndescribe('Actionable', () => {\n  @controller\n  class BindTestElement extends HTMLElement {\n    foo = fake()\n    bar = fake()\n    handleEvent = fake()\n  }\n  let instance: BindTestElement\n  beforeEach(async () => {\n    instance = await fixture(html`<bind-test data-action=\"foo:bind-test#foo\">\n        <div id=\"el1\" data-action=\"click:bind-test#foo\"></div>\n        <div id=\"el2\" data-action=\"custom:event:bind-test#foo click:other-controller#foo\"></div>\n        <div id=\"el3\" data-action=\"click:bind-test#baz focus:bind-test#foo submit:bind-test#foo\"></div>\n        <div id=\"el4\" data-action=\"handle:bind-test other:bind-test\"></div>\n        <div\n          id=\"el5\"\n          data-action=\"\n            click:bind-test#foo\n            click:bind-test#bar\n          \"\n        ></div>\n      </bind-test>\n      <div id=\"el6\" data-action=\"click:bind-test#foo\"></div>`)\n  })\n\n  it('binds events on elements based on their data-action attribute', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el1')!.click()\n    expect(instance.foo).to.have.callCount(1)\n  })\n\n  it('allows for the presence of `:` in an event name', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el2')!.dispatchEvent(new CustomEvent('custom:event'))\n    expect(instance.foo).to.have.callCount(1)\n  })\n\n  it('binds events on the controller to itself', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.dispatchEvent(new CustomEvent('foo'))\n    expect(instance.foo).to.have.callCount(1)\n  })\n\n  it('does not bind elements whose closest selector is not this controller', () => {\n    instance.ownerDocument.querySelector<HTMLElement>('#el6')!.click()\n    expect(instance.foo).to.have.callCount(0)\n  })\n\n  it('does not bind elements whose data-action does not match controller tagname', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el2')!.click()\n    expect(instance.foo).to.have.callCount(0)\n  })\n\n  it('does not bind methods that dont exist', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el3')!.click()\n    expect(instance.foo).to.have.callCount(0)\n  })\n\n  it('can bind multiple event types', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el3')!.dispatchEvent(new CustomEvent('focus'))\n    expect(instance.foo).to.have.callCount(1)\n    instance.querySelector<HTMLElement>('#el3')!.dispatchEvent(new CustomEvent('submit'))\n    expect(instance.foo).to.have.callCount(2)\n    expect(instance.foo.getCall(0).args[0].type).to.equal('focus')\n    expect(instance.foo.getCall(1).args[0].type).to.equal('submit')\n  })\n\n  it('binds to `handleEvent` is function name is omitted', () => {\n    expect(instance.handleEvent).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el4')!.dispatchEvent(new CustomEvent('handle'))\n    expect(instance.handleEvent).to.have.callCount(1)\n    instance.querySelector<HTMLElement>('#el4')!.dispatchEvent(new CustomEvent('other'))\n    expect(instance.handleEvent).to.have.callCount(2)\n    expect(instance.handleEvent.getCall(0).args[0].type).to.equal('handle')\n    expect(instance.handleEvent.getCall(1).args[0].type).to.equal('other')\n  })\n\n  it('can bind multiple actions separated by line feed', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el5')!.dispatchEvent(new CustomEvent('click'))\n    expect(instance.foo).to.have.callCount(1)\n    expect(instance.bar).to.have.callCount(1)\n    expect(instance.foo.getCall(0).args[0].type).to.equal('click')\n    expect(instance.bar.getCall(0).args[0].type).to.equal('click')\n  })\n\n  it('can bind multiple elements to the same event', () => {\n    expect(instance.foo).to.have.callCount(0)\n    instance.querySelector<HTMLElement>('#el1')!.click()\n    expect(instance.foo).to.have.callCount(1)\n    instance.querySelector<HTMLElement>('#el5')!.click()\n    expect(instance.foo).to.have.callCount(2)\n    expect(instance.foo.getCall(0).args[0].target.id).to.equal('el1')\n    expect(instance.foo.getCall(1).args[0].target.id).to.equal('el5')\n  })\n\n  it('binds elements added to elements subtree', async () => {\n    const el1 = document.createElement('div')\n    const el2 = document.createElement('div')\n    el1.setAttribute('data-action', 'click:bind-test#foo')\n    el2.setAttribute('data-action', 'submit:bind-test#foo')\n    instance.append(el1, el2)\n\n    // We need to wait for one microtask after injecting the HTML into to\n    // controller so that the actions have been bound to the controller.\n    await Promise.resolve()\n\n    expect(instance.foo).to.have.callCount(0)\n    el1.click()\n    expect(instance.foo).to.have.callCount(1)\n    el2.dispatchEvent(new CustomEvent('submit'))\n    expect(instance.foo).to.have.callCount(2)\n  })\n\n  it('can bind elements within the shadowDOM', async () => {\n    const el1 = document.createElement('div')\n    const el2 = document.createElement('div')\n    el1.setAttribute('data-action', 'click:bind-test#foo')\n    el2.setAttribute('data-action', 'submit:bind-test#foo')\n    const shadowRoot = instance.attachShadow({mode: 'open'})\n    bindShadow(shadowRoot)\n    shadowRoot.append(el1, el2)\n\n    // We need to wait for one microtask after injecting the HTML into to\n    // controller so that the actions have been bound to the controller.\n    await Promise.resolve()\n\n    expect(instance.foo).to.have.callCount(0)\n    el1.click()\n    expect(instance.foo).to.have.callCount(1)\n    el2.dispatchEvent(new CustomEvent('submit'))\n    expect(instance.foo).to.have.callCount(2)\n  })\n\n  describe('mutations', () => {\n    it('re-binds actions that are denoted by HTML that is dynamically injected into the controller', async function () {\n      const button = document.createElement('button')\n      button.setAttribute('data-action', 'click:bind-test#foo')\n      instance.appendChild(button)\n\n      // We need to wait for one microtask after injecting the HTML into to\n      // controller so that the actions have been bound to the controller.\n      await Promise.resolve()\n\n      button.click()\n      expect(instance.foo).to.have.callCount(1)\n    })\n\n    it('binds elements mutated in shadowDOM', async () => {\n      const el1 = document.createElement('div')\n      const el2 = document.createElement('div')\n      const shadowRoot = instance.attachShadow({mode: 'open'})\n      bindShadow(shadowRoot)\n      shadowRoot.append(el1, el2)\n\n      // We need to wait for one microtask after injecting the HTML into to\n      // controller so that the actions have been bound to the controller.\n      await Promise.resolve()\n\n      el1.click()\n      expect(instance.foo).to.have.callCount(0)\n\n      el1.setAttribute('data-action', 'click:bind-test#foo')\n      el2.setAttribute('data-action', 'submit:bind-test#foo')\n\n      // We need to wait for one microtask after injecting the HTML into to\n      // controller so that the actions have been bound to the controller.\n      await Promise.resolve()\n\n      expect(instance.foo).to.have.callCount(0)\n      el1.click()\n      expect(instance.foo).to.have.callCount(1)\n      el2.dispatchEvent(new CustomEvent('submit'))\n      expect(instance.foo).to.have.callCount(2)\n    })\n\n    it('re-binds actions deeply in the HTML', async function () {\n      instance.innerHTML = `\n          <div>\n            <div>\n              <button data-action=\"click:bind-test#foo\">\n            </div>\n          </div>\n        `\n      // We need to wait for one microtask after injecting the HTML into to\n      // controller so that the actions have been bound to the controller.\n      await Promise.resolve()\n\n      instance.querySelector('button')!.click()\n      expect(instance.foo).to.have.callCount(1)\n    })\n\n    it('will not fire if the binding attribute is removed', () => {\n      expect(instance.foo).to.have.callCount(0)\n      const el = instance.querySelector<HTMLElement>('#el1')!\n\n      el.click()\n      expect(instance.foo).to.have.callCount(1)\n      el.setAttribute('data-action', 'click:other-element#foo')\n      el.click()\n      expect(instance.foo).to.have.callCount(1)\n    })\n\n    it('will rebind elements if the attribute changes', async function () {\n      expect(instance.foo).to.have.callCount(0)\n      const el = instance.querySelector<HTMLElement>('#el1')!\n\n      el.click()\n      expect(instance.foo).to.have.callCount(1)\n      el.setAttribute('data-action', 'submit:bind-test#foo')\n      el.click()\n      expect(instance.foo).to.have.callCount(1)\n\n      // We need to wait for one microtask after injecting the HTML into to\n      // controller so that the actions have been bound to the controller.\n      await Promise.resolve()\n\n      el.dispatchEvent(new CustomEvent('submit'))\n      expect(instance.foo).to.have.callCount(2)\n    })\n  })\n})\n"
  },
  {
    "path": "test/controllable.ts",
    "content": "import type {CustomElementClass, CustomElement} from '../src/custom-element.js'\nimport {expect, fixture, html} from '@open-wc/testing'\nimport {fake} from 'sinon'\nimport {controllable, attachShadowCallback, attachInternalsCallback} from '../src/controllable.js'\n\ndescribe('controllable', () => {\n  describe('attachShadowCallback', () => {\n    let attachShadowFake: (shadow: ShadowRoot) => void\n    let shadow: ShadowRoot | null\n    beforeEach(() => {\n      shadow = null\n      attachShadowFake = fake()\n    })\n\n    const attachShadow = <T extends CustomElementClass>(Class: T): T =>\n      class extends controllable(Class) {\n        [attachShadowCallback](...args: [ShadowRoot]) {\n          super[attachShadowCallback]?.(...args)\n          return attachShadowFake.apply(this, args)\n        }\n      }\n\n    @attachShadow\n    @controllable\n    class DeclarativeShadowAbility extends HTMLElement {\n      constructor() {\n        super()\n        // Declarative shadows run before constructor() is available, but\n        // abilities run after element constructor\n        shadow = HTMLElement.prototype.attachShadow.call(this, {mode: 'closed'})\n      }\n      [attachShadowCallback]() {\n        throw new Error('Custom Element concrete class [attachShadowCallback] should not have been called')\n      }\n    }\n    customElements.define('declarative-shadow-ability', DeclarativeShadowAbility)\n\n    @attachShadow\n    @controllable\n    class ClosedShadowAbility extends HTMLElement {\n      constructor() {\n        super()\n        shadow = this.attachShadow({mode: 'closed'})\n      }\n      [attachShadowCallback]() {\n        throw new Error('Custom Element concrete class [attachShadowCallback] should not have been called')\n      }\n    }\n    customElements.define('closed-shadow-ability', ClosedShadowAbility)\n\n    @attachShadow\n    @controllable\n    class ConnectedShadowAbility extends HTMLElement {\n      connectedCallback() {\n        shadow = this.attachShadow({mode: 'closed'})\n      }\n      [attachShadowCallback]() {\n        throw new Error('Custom Element concrete class [attachShadowCallback] should not have been called')\n      }\n    }\n    customElements.define('connected-shadow-ability', ConnectedShadowAbility)\n\n    @attachShadow\n    @controllable\n    class ManualShadowAbility extends HTMLElement {\n      [attachShadowCallback]() {\n        throw new Error('Custom Element concrete class [attachShadowCallback] should not have been called')\n      }\n    }\n    customElements.define('manual-shadow-ability', ManualShadowAbility)\n\n    @attachShadow\n    @controllable\n    class DisallowedShadowAbility extends HTMLElement {\n      static disabledFeatures = ['shadow']\n    }\n    customElements.define('disallowed-shadow-ability', DisallowedShadowAbility)\n\n    it('is called with shadowRoot of declarative ShadowDOM', async () => {\n      const instance = await fixture(html`<declarative-shadow-ability></declarative-shadow-ability>`)\n      expect(shadow).to.exist.and.be.instanceof(ShadowRoot)\n      expect(attachShadowFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(shadow)\n    })\n\n    it('is called with shadowRoot from attachShadow call', async () => {\n      const instance = await fixture(html`<manual-shadow-ability></manual-shadow-ability>`)\n      shadow = instance.attachShadow({mode: 'closed'})\n      expect(shadow).to.exist.and.be.instanceof(ShadowRoot)\n      expect(attachShadowFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(shadow)\n    })\n\n    it('is called with shadowRoot from attachInternals call', async () => {\n      const instance = await fixture(html`<closed-shadow-ability></closed-shadow-ability>`)\n      expect(shadow).to.exist.and.be.instanceof(ShadowRoot)\n      expect(attachShadowFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(shadow)\n    })\n\n    it('is called with shadowRoot from connectedCallback', async () => {\n      const instance = await fixture(html`<connected-shadow-ability></connected-shadow-ability>`)\n      expect(shadow).to.exist.and.be.instanceof(ShadowRoot)\n      expect(attachShadowFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(shadow)\n    })\n\n    it('does not error if shadowdom is disabled', async () => {\n      await fixture(html`<disabled-shadow-ability></disabled-shadow-ability>`)\n      expect(attachShadowFake).to.be.have.callCount(0)\n    })\n  })\n\n  describe('attachInternalsCallback', () => {\n    let attachInternalsFake: (internals: ElementInternals) => void\n    let internals: ElementInternals | null\n    beforeEach(() => {\n      internals = null\n      attachInternalsFake = fake()\n    })\n\n    const attachInternals = <T extends CustomElementClass>(Class: T): T =>\n      class extends controllable(Class) {\n        [attachInternalsCallback](...args: [ElementInternals]) {\n          super[attachInternalsCallback]?.(...args)\n          return attachInternalsFake.apply(this, args)\n        }\n      }\n\n    @attachInternals\n    @controllable\n    class InternalsAbility extends HTMLElement {\n      constructor() {\n        super()\n        internals = this.attachInternals()\n      }\n      [attachInternalsCallback]() {\n        throw new Error('Custom Element concrete class [attachInternalsCallback] should not have been called')\n      }\n    }\n    customElements.define('internals-ability', InternalsAbility)\n\n    @attachInternals\n    @controllable\n    class ManualInternalsAbility extends HTMLElement {\n      [attachInternalsCallback]() {\n        throw new Error('Custom Element concrete class [attachInternalsCallback] should not have been called')\n      }\n    }\n    customElements.define('manual-internals-ability', ManualInternalsAbility)\n\n    @attachInternals\n    @controllable\n    class DisallowedInternalsAbility extends HTMLElement {\n      static disabledFeatures = ['internals'];\n      [attachInternalsCallback]() {\n        throw new Error('Custom Element concrete class [attachInternalsCallback] should not have been called')\n      }\n    }\n    customElements.define('disallowed-internals-ability', DisallowedInternalsAbility)\n\n    it('is called on constructor', async () => {\n      const instance = await fixture(html`<manual-internals-ability></manual-internals-ability>`)\n      expect(attachInternalsFake).to.be.calledOnce.calledOn(instance)\n    })\n\n    it('does not prevent attachInternals being called by userland class', async () => {\n      const instance = await fixture(html`<internals-ability></internals-ability>`)\n      expect(internals).to.exist.and.be.instanceof(ElementInternals)\n      expect(attachInternalsFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(internals)\n    })\n\n    it('errors if userland calls attachInternals more than once', async () => {\n      const instance = await fixture<CustomElement>(html`<manual-internals-ability></manual-internals-ability>`)\n      internals = instance.attachInternals()\n      expect(internals).to.exist.and.be.instanceof(ElementInternals)\n      expect(attachInternalsFake).to.be.calledOnce.calledOn(instance).and.calledWithExactly(internals)\n\n      expect(() => instance.attachInternals()).to.throw(DOMException)\n    })\n\n    it('does not error if element internals are disabled', async () => {\n      await fixture(html`<disallowed-internals-ability></disallowed-internals-ability>`)\n      expect(attachInternalsFake).to.have.callCount(0)\n    })\n  })\n})\n"
  },
  {
    "path": "test/controller.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {replace, fake, spy} from 'sinon'\nimport {controller} from '../src/controller.js'\nimport {attr} from '../src/attr.js'\nimport {lazyDefine} from '../src/lazy-define.js'\n\ndescribe('controller', () => {\n  let instance\n\n  it('calls register', async () => {\n    @controller\n    class ControllerRegisterElement extends HTMLElement {}\n    instance = await fixture(html`<controller-register />`)\n    expect(instance).to.be.instanceof(ControllerRegisterElement)\n  })\n\n  it('registers element with custom name when provided', async () => {\n    @controller('happy-widget')\n    class SomeClass extends HTMLElement {}\n    instance = await fixture(html`<happy-widget />`)\n    expect(instance).to.be.instanceof(SomeClass)\n  })\n\n  it('registers element with custom name using function syntax', async () => {\n    controller('custom-element-name')(class AnotherClass extends HTMLElement {})\n    instance = await fixture(html`<custom-element-name />`)\n    expect(instance).to.exist\n  })\n\n  it('adds data-catalyst to elements with custom names', async () => {\n    @controller('custom-named-element')\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    class CustomNamedElement extends HTMLElement {}\n\n    instance = await fixture(html`<custom-named-element />`)\n    expect(instance.hasAttribute('data-catalyst')).to.equal(true)\n    expect(instance.getAttribute('data-catalyst')).to.equal('')\n  })\n\n  it('adds data-catalyst to elements', async () => {\n    @controller\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    class ControllerDataAttrElement extends HTMLElement {}\n\n    instance = await fixture(html`<controller-data-attr />`)\n    expect(instance.hasAttribute('data-catalyst')).to.equal(true)\n    expect(instance.getAttribute('data-catalyst')).to.equal('')\n  })\n\n  it('binds controllers before custom connectedCallback behaviour', async () => {\n    @controller\n    class ControllerBindOrderElement extends HTMLElement {\n      foo = fake()\n    }\n    @controller\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    class ControllerBindOrderSubElement extends HTMLElement {\n      connectedCallback() {\n        this.dispatchEvent(new CustomEvent('loaded'))\n      }\n    }\n    instance = await fixture<ControllerBindOrderElement>(html`\n      <controller-bind-order>\n        <controller-bind-order-sub data-action=\"loaded:controller-bind-order#foo\" />\n      </controller-bind-order>\n    `)\n    expect(instance.foo).to.have.callCount(1)\n  })\n\n  it('binds shadowRoots after connectedCallback behaviour', async () => {\n    @controller\n    class ControllerBindShadowElement extends HTMLElement {\n      connectedCallback() {\n        this.attachShadow({mode: 'open'})\n        const button = document.createElement('button')\n        button.setAttribute('data-action', 'click:controller-bind-shadow#foo')\n        this.shadowRoot!.appendChild(button)\n      }\n\n      foo() {\n        return 'foo'\n      }\n    }\n    instance = await fixture<ControllerBindShadowElement>(html`<controller-bind-shadow />`)\n    replace(instance, 'foo', fake(instance.foo))\n\n    instance.shadowRoot!.querySelector('button')!.click()\n\n    expect(instance.foo).to.have.callCount(1)\n  })\n\n  it('observes changes on shadowRoots', async () => {\n    const onDefine = spy()\n    lazyDefine('nested-shadow-element', onDefine)\n\n    @controller\n    class ControllerObserveShadowElement extends HTMLElement {\n      connectedCallback() {\n        const shadowRoot = this.attachShadow({mode: 'open'})\n        // eslint-disable-next-line github/unescaped-html-literal\n        shadowRoot.innerHTML = '<div><nested-shadow-element></nested-shadow-element></div>'\n      }\n    }\n    instance = await fixture<ControllerObserveShadowElement>(html`<controller-observe-shadow />`)\n\n    expect(onDefine).to.be.callCount(1)\n  })\n\n  it('binds auto shadowRoots', async () => {\n    @controller\n    class ControllerBindAutoShadowElement extends HTMLElement {\n      foo() {\n        return 'foo'\n      }\n    }\n    instance = await fixture<ControllerBindAutoShadowElement>(html`\n      <controller-bind-auto-shadow>\n        <template data-shadowroot=\"open\">\n          <button data-action=\"click:controller-bind-auto-shadow#foo\" />\n        </template>\n      </controller-bind-auto-shadow>\n    `)\n    replace(instance, 'foo', fake(instance.foo))\n\n    expect(instance.shadowRoot).to.exist\n    expect(instance).to.have.property('shadowRoot').not.equal(null)\n    expect(instance.shadowRoot!.children).to.have.lengthOf(1)\n    instance.shadowRoot!.querySelector('button')!.click()\n\n    expect(instance.foo).to.have.callCount(1)\n  })\n\n  it('upgrades child decendants when connected', async () => {\n    @controller\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    class ChildElementElement extends HTMLElement {}\n    @controller\n    class ParentElementElement extends HTMLElement {\n      connectedCallback() {\n        const child = this.querySelector('child-element')!\n        expect(child.matches(':defined')).to.equal(true)\n      }\n    }\n\n    instance = await fixture<ParentElementElement>(html`\n      <parent-element>\n        <child-element />\n      </parent-element>\n    `)\n  })\n\n  describe('attrs', () => {\n    let attrValues: string[] = []\n    @controller\n    class AttributeTestElement extends HTMLElement {\n      foo = 'baz'\n      attributeChangedCallback() {\n        attrValues.push(this.getAttribute('data-foo')!)\n        attrValues.push(this.foo)\n      }\n    }\n    attr(AttributeTestElement.prototype, 'foo')\n\n    beforeEach(() => {\n      attrValues = []\n    })\n\n    it('initializes attrs as attributes in attributeChangedCallback', async () => {\n      instance = await fixture<AttributeTestElement>(html`<attribute-test></attribute-test>`)\n      instance.foo = 'bar'\n      instance.attributeChangedCallback()\n      expect(attrValues).to.eql(['bar', 'bar'])\n    })\n\n    it('initializes attributes as attrs in attributeChangedCallback', async () => {\n      instance = await fixture<AttributeTestElement>(html`<attribute-test />`)\n      instance.setAttribute('data-foo', 'bar')\n      instance.attributeChangedCallback()\n      expect(attrValues).to.eql(['bar', 'bar'])\n    })\n  })\n})\n"
  },
  {
    "path": "test/dasherize.ts",
    "content": "import {expect} from '@open-wc/testing'\nimport {dasherize} from '../src/dasherize.js'\n\ndescribe('dasherize', () => {\n  const tests: Array<[PropertyKey, string]> = [\n    ['json', 'json'],\n    ['fooBar', 'foo-bar'],\n    ['FooBar', 'foo-bar'],\n    ['autofocusWhenReady', 'autofocus-when-ready'],\n    ['URLBar', 'url-bar'],\n    ['ClipX', 'clip-x'],\n    [Symbol('helloWorld'), 'hello-world']\n  ]\n\n  tests.map(([input, output]) =>\n    it(`transforms ${String(input)} to ${output}`, () => expect(dasherize(input)).to.equal(output))\n  )\n})\n"
  },
  {
    "path": "test/lazy-define.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {spy} from 'sinon'\nimport {lazyDefine, observe} from '../src/lazy-define.js'\n\nconst animationFrame = () => new Promise<unknown>(resolve => requestAnimationFrame(resolve))\n\ndescribe('lazyDefine', () => {\n  describe('ready strategy', () => {\n    it('calls define for a lazy component', async () => {\n      const onDefine = spy()\n      lazyDefine('scan-document-test', onDefine)\n      await fixture(html`<scan-document-test></scan-document-test>`)\n\n      await animationFrame()\n\n      expect(onDefine).to.be.callCount(1)\n    })\n\n    it('initializes dynamic elements that are defined after the document is ready', async () => {\n      const onDefine = spy()\n      await fixture(html`<later-defined-element-test></later-defined-element-test>`)\n      lazyDefine('later-defined-element-test', onDefine)\n\n      await animationFrame()\n\n      expect(onDefine).to.be.callCount(1)\n    })\n\n    it(\"doesn't call the same callback twice\", async () => {\n      const onDefine = spy()\n      lazyDefine('twice-defined-element', onDefine)\n      lazyDefine('once-defined-element', onDefine)\n      lazyDefine('twice-defined-element', onDefine)\n      await fixture(html`\n        <once-defined-element></once-defined-element>\n        <once-defined-element></once-defined-element>\n        <once-defined-element></once-defined-element>\n        <twice-defined-element></twice-defined-element>\n        <twice-defined-element></twice-defined-element>\n        <twice-defined-element></twice-defined-element>\n        <twice-defined-element></twice-defined-element>\n      `)\n\n      await animationFrame()\n\n      expect(onDefine).to.be.callCount(2)\n    })\n\n    it('takes an object as well', async () => {\n      const onDefine1 = spy()\n      const onDefine2 = spy()\n      const onDefine3 = spy()\n      lazyDefine({\n        'first-object-element': onDefine1,\n        'second-object-element': onDefine2,\n        'third-object-element': onDefine3\n      })\n      await fixture(html`\n        <first-object-element></first-object-element>\n        <second-object-element></second-object-element>\n        <third-object-element></third-object-element>\n      `)\n\n      await animationFrame()\n\n      expect(onDefine1).to.have.callCount(1)\n      expect(onDefine2).to.have.callCount(1)\n      expect(onDefine3).to.have.callCount(1)\n    })\n\n    it('coalesces multiple added elements into a single rAF callback', async () => {\n      const onDefine = spy()\n      lazyDefine('coalesce-test-element', onDefine)\n\n      const rafSpy = spy(window, 'requestAnimationFrame')\n      const callsBefore = rafSpy.callCount\n\n      await fixture(html`\n        <div>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n          <coalesce-test-element></coalesce-test-element>\n        </div>\n      `)\n\n      await animationFrame()\n\n      const rafCallsFromScan = rafSpy.callCount - callsBefore\n      rafSpy.restore()\n\n      // Should use at most a few rAF calls, not one per element\n      expect(rafCallsFromScan).to.be.lessThan(5)\n      expect(onDefine).to.be.callCount(1)\n    })\n\n    it('lazy loads elements in shadow roots', async () => {\n      const onDefine = spy()\n      lazyDefine('nested-shadow-element', onDefine)\n\n      const el = await fixture(html` <div></div> `)\n      const shadowRoot = el.attachShadow({mode: 'open'})\n      observe(shadowRoot)\n      // eslint-disable-next-line github/unescaped-html-literal\n      shadowRoot.innerHTML = '<div><nested-shadow-element></nested-shadow-element></div>'\n\n      await animationFrame()\n\n      expect(onDefine).to.be.callCount(1)\n    })\n  })\n\n  describe('firstInteraction strategy', () => {\n    it('calls define for a lazy component', async () => {\n      const onDefine = spy()\n      lazyDefine('scan-document-test', onDefine)\n      await fixture(html`<scan-document-test data-load-on=\"firstInteraction\"></scan-document-test>`)\n\n      await animationFrame()\n      expect(onDefine).to.be.callCount(0)\n\n      document.dispatchEvent(new Event('mousedown'))\n\n      await animationFrame()\n      expect(onDefine).to.be.callCount(1)\n    })\n  })\n  describe('visible strategy', () => {\n    it('calls define for a lazy component', async () => {\n      const onDefine = spy()\n      lazyDefine('scan-document-test', onDefine)\n      await fixture(\n        html`<div style=\"height: calc(100vh + 256px)\"></div>\n          <scan-document-test data-load-on=\"visible\"></scan-document-test>`\n      )\n      await animationFrame()\n      expect(onDefine).to.be.callCount(0)\n\n      document.documentElement.scrollTo({top: 10})\n\n      await animationFrame()\n      expect(onDefine).to.be.callCount(1)\n    })\n  })\n})\n"
  },
  {
    "path": "test/mark.ts",
    "content": "import {expect} from '@open-wc/testing'\nimport {fake} from 'sinon'\nimport {createMark} from '../src/mark.js'\n\ndescribe('createMark', () => {\n  it('returns a tuple of functions: mark, getMarks, initializeMarks', () => {\n    const mark = createMark(\n      () => {},\n      () => ({})\n    )\n    expect(mark).to.be.an('array').with.lengthOf(3)\n    expect(mark).to.have.property('0').a('function')\n    expect(mark).to.have.property('1').a('function')\n    expect(mark).to.have.property('2').a('function')\n  })\n\n  it('attaches a `static` unique symbol to the first function', () => {\n    const mark = createMark(\n      () => {},\n      () => ({})\n    )\n    expect(mark).to.have.nested.property('0.static').a('symbol')\n    const otherMark = createMark(\n      () => {},\n      () => ({})\n    )\n    expect(otherMark).to.have.nested.property('0.static').a('symbol').not.equal(mark[0].static)\n  })\n\n  it('can be added to class fields without errors', () => {\n    const [mark] = createMark(\n      () => {},\n      () => ({})\n    )\n    class FooBar {\n      @mark foo: unknown\n      @mark bar = 1\n      @mark baz = 'hi'\n    }\n    new FooBar()\n  })\n\n  it('can be added to getters or setters without errors', () => {\n    const [mark] = createMark(\n      () => {},\n      () => ({})\n    )\n    class FooBar {\n      @mark get foo() {\n        return 1\n      }\n      set foo(v: number) {}\n\n      @mark get bar() {\n        return 1\n      }\n      @mark set baz(v: number) {}\n    }\n    new FooBar()\n  })\n\n  it('can be added to methods without errors', () => {\n    const [mark] = createMark(\n      () => {},\n      () => ({})\n    )\n    class Foo {\n      @mark foo() {}\n    }\n    new Foo()\n  })\n\n  it('retrieves all marked fields with the get mark function', () => {\n    const [mark, getMark] = createMark(\n      () => {},\n      () => ({})\n    )\n    class FooBar {\n      @mark foo: unknown\n      @mark bar = 1\n      @mark baz = 'hi'\n      @mark get bing() {\n        return 1\n      }\n      @mark get qux() {\n        return 1\n      }\n      @mark set quuz(v: number) {}\n      @mark set corge(v: number) {}\n      @mark grault() {}\n    }\n    expect(getMark(new FooBar())).to.eql(new Set(['foo', 'bar', 'baz', 'bing', 'qux', 'quuz', 'corge', 'grault']))\n  })\n\n  it('retrieves marked symbol methods correctly', () => {\n    const [mark, getMark] = createMark(\n      () => {},\n      () => ({})\n    )\n    const sym = Symbol('foo')\n    class FooBar {\n      @mark [sym]() {}\n    }\n    expect(getMark(new FooBar()).has(sym)).to.equal(true)\n  })\n\n  it('retrieves fields declared using the `mark.static` symbol as a static class field', () => {\n    const [mark, getMark] = createMark(\n      () => {},\n      () => ({})\n    )\n    class FooBar {\n      static [mark.static] = ['bar', 'bing', 'quuz', 'grault']\n      @mark foo: unknown\n      bar = 1\n      @mark baz = 'hi'\n      get bing() {\n        return 1\n      }\n      @mark get qux() {\n        return 1\n      }\n      set quuz(v: number) {}\n      @mark set corge(v: number) {}\n      grault() {}\n    }\n    const instance = new FooBar()\n    expect(getMark(instance)).to.eql(new Set(['foo', 'baz', 'qux', 'corge', 'bar', 'bing', 'quuz', 'grault']))\n  })\n\n  it('will not contain duplicates', () => {\n    const [mark, getMark] = createMark(\n      () => {},\n      () => ({})\n    )\n    class FooBar {\n      static [mark.static] = ['bar', 'bing', 'quuz', 'grault']\n      @mark foo: unknown\n      @mark bar = 1\n      @mark baz = 'hi'\n      @mark get bing() {\n        return 1\n      }\n      @mark get qux() {\n        return 1\n      }\n      @mark set quuz(v: number) {}\n      @mark set corge(v: number) {}\n      @mark grault() {}\n    }\n    expect(getMark(new FooBar())).to.eql(new Set(['foo', 'bar', 'baz', 'bing', 'qux', 'quuz', 'corge', 'grault']))\n  })\n\n  it('calls the given validate function for each field, with name and kind', () => {\n    const validate = fake()\n    const [mark, getMarks] = createMark(validate, () => {})\n    const sym = Symbol('garply')\n    class FooBar {\n      static [mark.static] = ['bar', 'bing', 'quuz', 'grault']\n      @mark foo: unknown\n      bar = 1\n      @mark baz = 'hi'\n      get bing() {\n        return 1\n      }\n      @mark get qux() {\n        return 1\n      }\n      set quuz(v: number) {}\n      @mark set corge(v: number) {}\n      grault() {}\n      @mark [sym]() {}\n    }\n    getMarks(new FooBar())\n    expect(validate).to.be.calledWithExactly({name: 'foo', kind: 'field'})\n    expect(validate).to.be.calledWithExactly({name: 'bar', kind: 'field'})\n    expect(validate).to.be.calledWithExactly({name: 'baz', kind: 'field'})\n    expect(validate).to.be.calledWithExactly({name: 'bing', kind: 'getter'})\n    expect(validate).to.be.calledWithExactly({name: 'qux', kind: 'getter'})\n    expect(validate).to.be.calledWithExactly({name: 'quuz', kind: 'setter'})\n    expect(validate).to.be.calledWithExactly({name: 'corge', kind: 'setter'})\n    expect(validate).to.be.calledWithExactly({name: 'grault', kind: 'method'})\n    expect(validate).to.be.calledWithExactly({name: sym, kind: 'method'})\n  })\n\n  it('calls the given initialize function for each static defined field once initialized, with name, kind and access', () => {\n    const validate = fake()\n    const initialize = fake(({access}) => access)\n    const [mark, getMarks, initializeMarks] = createMark(validate, initialize)\n    const sym = Symbol('garply')\n    class FooBar {\n      static [mark.static] = ['bar', 'bing', 'quuz', 'grault']\n      @mark foo: unknown\n      bar = 1\n      @mark baz = 'hi'\n      get bing() {\n        return 1\n      }\n      @mark get qux() {\n        return 1\n      }\n      set quuz(v: number) {}\n      @mark set corge(v: number) {}\n      grault() {}\n      @mark [sym]() {}\n    }\n    const fooBar = new FooBar()\n    getMarks(fooBar)\n    expect(initialize).to.have.callCount(0)\n    initializeMarks(fooBar)\n    const accessFor = (field: PropertyKey) => Object.getOwnPropertyDescriptor(FooBar.prototype, field)\n    expect(initialize).to.be.calledWithExactly(fooBar, {\n      name: 'foo',\n      kind: 'field',\n      access: {value: void 0, configurable: true, writable: true, enumerable: true}\n    })\n    expect(initialize).to.be.calledWithExactly(fooBar, {\n      name: 'bar',\n      kind: 'field',\n      access: {value: 1, configurable: true, writable: true, enumerable: true}\n    })\n    expect(initialize).to.be.calledWithExactly(fooBar, {\n      name: 'baz',\n      kind: 'field',\n      access: {value: 'hi', configurable: true, writable: true, enumerable: true}\n    })\n    expect(initialize).to.be.calledWithExactly(fooBar, {name: 'bing', kind: 'getter', access: accessFor('bing')})\n    expect(initialize).to.be.calledWithExactly(fooBar, {name: 'qux', kind: 'getter', access: accessFor('qux')})\n    expect(initialize).to.be.calledWithExactly(fooBar, {name: 'quuz', kind: 'setter', access: accessFor('quuz')})\n    expect(initialize).to.be.calledWithExactly(fooBar, {name: 'corge', kind: 'setter', access: accessFor('corge')})\n    expect(initialize).to.be.calledWithExactly(fooBar, {name: 'grault', kind: 'method', access: accessFor('grault')})\n    expect(initialize).to.be.calledWithExactly(fooBar, {name: sym, kind: 'method', access: accessFor(sym)})\n  })\n\n  it('can apply multiple different marks to the same property', () => {\n    const [mark1, getMarks1, initializeMarks1] = createMark(\n      fake(),\n      fake(() => ({get: fake(), set: fake()}))\n    )\n    const [mark2, getMarks2, initializeMarks2] = createMark(\n      fake(),\n      fake(() => ({get: fake(), set: fake()}))\n    )\n    class FooBar {\n      @mark1 @mark2 foo: unknown\n      @mark2 @mark1 bar = 'hi'\n      constructor() {\n        initializeMarks1(this)\n        initializeMarks2(this)\n      }\n    }\n    const fooBar = new FooBar()\n    expect(Array.from(getMarks1(fooBar))).to.eql(['foo', 'bar'])\n    expect(Array.from(getMarks2(fooBar))).to.eql(['foo', 'bar'])\n  })\n})\n"
  },
  {
    "path": "test/providable.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {fake} from 'sinon'\nimport {provide, provideAsync, consume, providable, ContextEvent} from '../src/providable.js'\n\ndescribe('Providable', () => {\n  const sym = Symbol('bing')\n  @providable\n  class ProvidableProviderTest extends HTMLElement {\n    @provide foo = 'hello'\n    @provide bar = 'world'\n    @provide get baz() {\n      return 3\n    }\n    @provide [sym] = {provided: true}\n    @provide qux = 8\n  }\n  window.customElements.define('providable-provider-test', ProvidableProviderTest)\n\n  @providable\n  class AsyncProvidableProviderTest extends HTMLElement {\n    @provideAsync foo = Promise.resolve('hello')\n    @provideAsync bar = Promise.resolve('world')\n    @provideAsync get baz() {\n      return Promise.resolve(3)\n    }\n    @provideAsync [sym] = Promise.resolve({provided: true})\n    @provideAsync qux = Promise.resolve(8)\n  }\n  window.customElements.define('async-providable-provider-test', AsyncProvidableProviderTest)\n\n  @providable\n  class ProvidableSomeProviderTest extends HTMLElement {\n    @provide foo = 'greetings'\n    bar = 'universe'\n    baz = 18\n    @provide qux = 42\n  }\n  window.customElements.define('providable-some-provider-test', ProvidableSomeProviderTest)\n\n  @providable\n  class ProvidableConsumerTest extends HTMLElement {\n    @consume foo = 'goodbye'\n    @consume bar = 'universe'\n    @consume get baz() {\n      return 1\n    }\n    @consume [sym] = {}\n    count = 0\n    get qux() {\n      return this.count\n    }\n    @consume set qux(value: number) {\n      this.count += 1\n    }\n    connectedCallback() {\n      this.textContent = `${this.foo} ${this.bar}`\n    }\n  }\n  window.customElements.define('providable-consumer-test', ProvidableConsumerTest)\n\n  describe('consumer without provider', () => {\n    let instance: ProvidableConsumerTest\n    let events = fake()\n    beforeEach(async () => {\n      events = fake()\n      document.body.addEventListener('context-request', events)\n      instance = await fixture(html`<providable-consumer-test />`)\n    })\n    afterEach(() => {\n      document.body.removeEventListener('context-request', events)\n    })\n\n    it('uses the given values', () => {\n      expect(instance).to.have.property('foo', 'goodbye')\n      expect(instance).to.have.property('bar', 'universe')\n      expect(instance).to.have.property('baz', 1)\n      expect(instance).to.have.property(sym).eql({})\n      expect(instance).to.have.property('textContent', 'goodbye universe')\n    })\n\n    it('overrides the property definitions to not be setters', () => {\n      expect(() => (instance.foo = 'hello')).to.throw()\n      expect(() => (instance.bar = 'world')).to.throw()\n      // @ts-expect-error this was only a getter to begin with\n      expect(() => (instance.baz = 3)).to.throw()\n    })\n\n    it('emits the `context-request` event when connected, for each field', async () => {\n      expect(events).to.have.callCount(5)\n      const fooEvent = events.getCall(0).args[0]\n      expect(fooEvent).to.be.instanceof(ContextEvent)\n      expect(fooEvent).to.have.nested.property('context.name', 'foo')\n      expect(fooEvent).to.have.nested.property('context.initialValue', 'goodbye')\n      expect(fooEvent).to.have.property('multiple', true)\n      expect(fooEvent).to.have.property('bubbles', true)\n\n      const barEvent = events.getCall(1).args[0]\n      expect(barEvent).to.be.instanceof(ContextEvent)\n      expect(barEvent).to.have.nested.property('context.name', 'bar')\n      expect(barEvent).to.have.nested.property('context.initialValue', 'universe')\n      expect(barEvent).to.have.property('multiple', true)\n      expect(barEvent).to.have.property('bubbles', true)\n\n      const bazEvent = events.getCall(2).args[0]\n      expect(bazEvent).to.be.instanceof(ContextEvent)\n      expect(bazEvent).to.have.nested.property('context.name', 'baz')\n      expect(bazEvent).to.have.nested.property('context.initialValue', 1)\n      expect(bazEvent).to.have.property('multiple', true)\n      expect(bazEvent).to.have.property('bubbles', true)\n\n      const bingEvent = events.getCall(3).args[0]\n      expect(bingEvent).to.be.instanceof(ContextEvent)\n      expect(bingEvent).to.have.nested.property('context.name', sym)\n      expect(bingEvent).to.have.nested.property('context.initialValue').eql({})\n      expect(bingEvent).to.have.property('multiple', true)\n      expect(bingEvent).to.have.property('bubbles', true)\n\n      const quxEvent = events.getCall(4).args[0]\n      expect(quxEvent).to.be.instanceof(ContextEvent)\n      expect(quxEvent).to.have.nested.property('context.name', 'qux')\n      expect(quxEvent).to.have.nested.property('context.initialValue').eql(0)\n      expect(quxEvent).to.have.property('multiple', true)\n      expect(quxEvent).to.have.property('bubbles', true)\n    })\n\n    it('changes value based on callback new value', async () => {\n      expect(events).to.have.callCount(5)\n      const fooCallback = events.getCall(0).args[0].callback\n      fooCallback('hello')\n      expect(instance).to.have.property('foo', 'hello')\n      fooCallback('goodbye')\n      expect(instance).to.have.property('foo', 'goodbye')\n    })\n\n    it('disposes of past callbacks when given new ones', async () => {\n      const dispose1 = fake()\n      const dispose2 = fake()\n      expect(events).to.have.callCount(5)\n      const fooCallback = events.getCall(0).args[0].callback\n      fooCallback('hello', dispose1)\n      expect(dispose1).to.have.callCount(0)\n      expect(dispose2).to.have.callCount(0)\n      fooCallback('goodbye', dispose1)\n      expect(dispose1).to.have.callCount(0)\n      expect(dispose2).to.have.callCount(0)\n      fooCallback('greetings', dispose2)\n      expect(dispose1).to.have.callCount(1)\n      expect(dispose2).to.have.callCount(0)\n      fooCallback('hola', dispose1)\n      expect(dispose1).to.have.callCount(1)\n      expect(dispose2).to.have.callCount(1)\n    })\n  })\n\n  describe('provider', () => {\n    let provider: ProvidableProviderTest\n    beforeEach(async () => {\n      provider = await fixture(\n        html`<providable-provider-test\n          ><div>\n            <span><strong></strong></span></div\n        ></providable-provider-test>`\n      )\n    })\n\n    it('listens for `context-request` events, calling back with values', () => {\n      const fooCallback = fake()\n      provider.dispatchEvent(new ContextEvent({name: 'foo', initialValue: 'a'}, fooCallback, true))\n      expect(fooCallback).to.have.callCount(1).and.be.calledWith('hello')\n      const barCallback = fake()\n      provider.querySelector('strong')!.dispatchEvent(new ContextEvent({name: 'bar', initialValue: 'a'}, barCallback))\n      expect(barCallback).to.have.callCount(1).and.be.calledWith('world')\n    })\n\n    it('re-calls callback each time value changes', () => {\n      const fooCallback = fake()\n      provider.dispatchEvent(new ContextEvent({name: 'foo', initialValue: 'a'}, fooCallback, true))\n      expect(fooCallback).to.have.callCount(1).and.be.calledWith('hello')\n      provider.foo = 'goodbye'\n      expect(fooCallback).to.have.callCount(2).and.be.calledWith('goodbye')\n      provider.foo = 'greetings'\n      expect(fooCallback).to.have.callCount(3).and.be.calledWith('greetings')\n    })\n\n    it('does not re-call callback if `multiple` is `false`', () => {\n      const fooCallback = fake()\n      provider.dispatchEvent(new ContextEvent({name: 'foo', initialValue: 'a'}, fooCallback, false))\n      expect(fooCallback).to.have.callCount(1).and.be.calledWith('hello')\n      provider.foo = 'goodbye'\n      expect(fooCallback).to.have.callCount(1)\n    })\n\n    it('does not re-call callback once `dispose` has been called', () => {\n      const fooCallback = fake()\n      provider.dispatchEvent(new ContextEvent({name: 'foo', initialValue: 'a'}, fooCallback, true))\n      expect(fooCallback).to.have.callCount(1).and.be.calledWith('hello')\n      const dispose = fooCallback.getCall(0).args[1]\n      dispose()\n      provider.foo = 'goodbye'\n      expect(fooCallback).to.have.callCount(1)\n    })\n  })\n\n  describe('consumer with provider parent', () => {\n    let provider: ProvidableProviderTest\n    let consumer: ProvidableConsumerTest\n    beforeEach(async () => {\n      provider = await fixture(html`<providable-provider-test>\n        <main>\n          <article>\n            <section>\n              <div>\n                <providable-consumer-test></providable-consumer-test>\n              </div>\n            </section>\n          </article>\n        </main>\n      </providable-provider-test>`)\n      consumer = provider.querySelector<ProvidableConsumerTest>('providable-consumer-test')!\n    })\n\n    it('uses values provided by provider', () => {\n      expect(consumer).to.have.property('foo', 'hello')\n      expect(consumer).to.have.property('bar', 'world')\n      expect(consumer).to.have.property('baz', 3)\n      expect(consumer).to.have.property(sym).eql({provided: true})\n      expect(consumer).to.have.property('qux').eql(8)\n    })\n\n    it('updates values provided if they change', () => {\n      expect(provider).to.have.property('foo', 'hello')\n      expect(consumer).to.have.property('foo', 'hello')\n      provider.foo = 'greetings'\n      expect(consumer).to.have.property('foo', 'greetings')\n    })\n\n    it('calls consumer set callbacks when the value is updated', () => {\n      expect(consumer).to.have.property('qux', 8)\n      expect(consumer).to.have.property('count', 1)\n      provider.qux = 17\n      expect(consumer).to.have.property('qux', 17)\n      expect(consumer).to.have.property('count', 2)\n      provider.qux = 18\n      expect(consumer).to.have.property('qux', 18)\n      expect(consumer).to.have.property('count', 3)\n    })\n  })\n\n  describe('consumer with nested provider parents', () => {\n    let provider: ProvidableProviderTest\n    let someProvider: ProvidableSomeProviderTest\n    let consumer: ProvidableConsumerTest\n    beforeEach(async () => {\n      provider = await fixture(html`<providable-provider-test>\n        <main>\n          <article>\n            <providable-some-provider-test>\n              <section>\n                <div>\n                  <providable-consumer-test></providable-consumer-test>\n                </div>\n              </section>\n            </providable-some-provider-test>\n          </article>\n        </main>\n      </providable-provider-test>`)\n      someProvider = provider.querySelector<ProvidableSomeProviderTest>('providable-some-provider-test')!\n      consumer = provider.querySelector<ProvidableConsumerTest>('providable-consumer-test')!\n    })\n\n    it('only recieves provider responses from first matching provider', () => {\n      expect(consumer).to.have.property('foo', 'greetings')\n      expect(consumer).to.have.property('bar', 'world')\n      expect(consumer).to.have.property('baz', 3)\n      expect(consumer).to.have.property(sym).eql({provided: true})\n      expect(consumer).to.have.property('qux').eql(42)\n      expect(consumer).to.have.property('count').eql(1)\n    })\n\n    it('only updates on appropriate provider changing values', () => {\n      expect(consumer).to.have.property('qux').eql(42)\n      expect(consumer).to.have.property('count').eql(1)\n      provider.qux = 12\n      expect(consumer).to.have.property('qux').eql(42)\n      expect(consumer).to.have.property('count').eql(1)\n      someProvider.qux = 88\n      expect(consumer).to.have.property('qux').eql(88)\n      expect(consumer).to.have.property('count').eql(2)\n    })\n  })\n\n  describe('async provider', () => {\n    let provider: AsyncProvidableProviderTest\n    let consumer: ProvidableConsumerTest\n    beforeEach(async () => {\n      provider = await fixture(html`<async-providable-provider-test>\n        <providable-consumer-test></providable-consumer-test>\n      </async-providable-provider-test>`)\n      consumer = provider.querySelector<ProvidableConsumerTest>('providable-consumer-test')!\n    })\n\n    it('passes resovled values to consumer', async () => {\n      expect(consumer).to.have.property('foo', 'hello')\n      expect(consumer).to.have.property('bar', 'world')\n      expect(consumer).to.have.property('baz', 3)\n      expect(consumer).to.have.property(sym).eql({provided: true})\n      expect(consumer).to.have.property('qux').eql(8)\n      expect(consumer).to.have.property('count').eql(1)\n    })\n  })\n\n  describe('error scenarios', () => {\n    it('cannot decorate methods as providers', () => {\n      expect(() => {\n        class Foo {\n          @provide foo() {}\n        }\n        new Foo()\n      }).to.throw(/provide cannot decorate method/)\n    })\n\n    it('cannot decorate setters as providers', () => {\n      expect(() => {\n        class Foo {\n          @provide set foo(v: string) {}\n        }\n        new Foo()\n      }).to.throw(/provide cannot decorate setter/)\n    })\n\n    it('cannot decorate methods as consumers', () => {\n      expect(() => {\n        class Foo {\n          @consume foo() {}\n        }\n        new Foo()\n      }).to.throw(/consume cannot decorate method/)\n    })\n  })\n})\n"
  },
  {
    "path": "test/register.ts",
    "content": "import {expect} from '@open-wc/testing'\nimport {restore, replace, fake} from 'sinon'\nimport {register} from '../src/register.js'\n\ndescribe('register', () => {\n  afterEach(() => {\n    restore()\n  })\n\n  it('registers the class as a custom element, normalising the class name', () => {\n    @register\n    class MyFirstClass extends HTMLElement {}\n    expect(window.customElements.get('my-first-class')).to.equal(MyFirstClass)\n  })\n\n  it('does not register controllers that already exist', () => {\n    {\n      @register\n      class MySecondClass extends HTMLElement {}\n      expect(window.customElements.get('my-second-class')).to.equal(MySecondClass)\n    }\n    {\n      @register\n      class MySecondClass extends HTMLElement {}\n      expect(window.customElements.get('my-second-class')).to.not.equal(MySecondClass)\n    }\n  })\n\n  it('will redefine controllers, catching on errors', () => {\n    replace(customElements, 'define', fake())\n    replace(\n      customElements,\n      'get',\n      fake(() => class extends HTMLElement {})\n    )\n    {\n      @register\n      class MyThirdClass extends HTMLElement {}\n      expect(customElements.define).to.be.calledOnceWithExactly('my-third-class', MyThirdClass)\n    }\n    expect(() => {\n      @register\n      class MyThirdClass extends HTMLElement {}\n      expect(customElements.define).to.be.calledOnceWithExactly('my-third-class', MyThirdClass)\n    }).to.throw(Error)\n  })\n\n  it('dasherises class names', () => {\n    @register\n    class ThisIsAnExampleOfDasherisedClassNames extends HTMLElement {}\n    expect(window.customElements.get('this-is-an-example-of-dasherised-class-names')).to.equal(\n      ThisIsAnExampleOfDasherisedClassNames\n    )\n  })\n\n  it('will intuitively dasherize acryonyms', () => {\n    @register\n    class URLBar extends HTMLElement {}\n    expect(window.customElements.get('url-bar')).to.equal(URLBar)\n  })\n\n  it('dasherizes cap suffixed names correctly', () => {\n    @register\n    class ClipX extends HTMLElement {}\n    expect(window.customElements.get('clip-x')).to.equal(ClipX)\n  })\n\n  it('automatically drops the `Element` suffix', () => {\n    @register\n    class FirstSuffixElement extends HTMLElement {}\n    expect(window.customElements.get('first-suffix')).to.equal(FirstSuffixElement)\n  })\n})\n"
  },
  {
    "path": "test/tag-observer.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {fake, match} from 'sinon'\nimport {registerTag, observeElementForTags} from '../src/tag-observer.js'\n\ndescribe('tag observer', () => {\n  let instance: HTMLElement\n  beforeEach(async () => {\n    instance = await fixture(html`<section>\n      <div data-tagtest=\"section.a.b.c section.d.e.f doesntexist.g.h.i\"></div>\n    </section>`)\n  })\n\n  it('can register new tag observers', () => {\n    registerTag('foo', fake(), fake())\n  })\n\n  it('throws an error when registering a duplicate', () => {\n    registerTag('duplicate', fake(), fake())\n    expect(() => registerTag('duplicate', fake(), fake())).to.throw()\n  })\n\n  describe('registered behaviour', () => {\n    const testParse = fake(v => v.split('.'))\n    const testFound = fake()\n    registerTag('data-tagtest', testParse, testFound)\n    beforeEach(() => {\n      observeElementForTags(instance)\n    })\n\n    it('uses parse to extract tagged element values', () => {\n      expect(testParse).to.be.calledWithExactly('section.a.b.c')\n      expect(testParse).to.be.calledWithExactly('section.d.e.f')\n      expect(testParse).to.be.calledWithExactly('doesntexist.g.h.i')\n    })\n\n    it('calls found with el and args based from testParse', () => {\n      const div = instance.querySelector('div')!\n      expect(testFound).to.be.calledWithExactly(div, instance, 'data-tagtest', 'a', 'b', 'c')\n      expect(testFound).to.be.calledWithExactly(div, instance, 'data-tagtest', 'd', 'e', 'f')\n      expect(testFound).to.not.be.calledWithMatch(match.any, match.any, 'data-tagtest', 'g', 'h', 'i')\n    })\n\n    it('calls found if added to a node that has tags on itself', () => {\n      const div = document.createElement('div')\n      div.setAttribute('data-tagtest', 'div.j.k.l')\n      observeElementForTags(div)\n      expect(testParse).to.be.calledWithExactly('div.j.k.l')\n      expect(testFound).to.be.calledWithExactly(div, div, 'data-tagtest', 'j', 'k', 'l')\n    })\n\n    it('pierces shadowdom boundaries to find nearest controller', () => {\n      const div = document.createElement('div')\n      const shadow = div.attachShadow({mode: 'open'})\n      const span = document.createElement('span')\n      span.setAttribute('data-tagtest', 'div.m.n.o')\n      shadow.append(span)\n      observeElementForTags(span)\n      expect(testParse).to.be.calledWithExactly('div.m.n.o')\n      expect(testFound).to.be.calledWithExactly(span, div, 'data-tagtest', 'm', 'n', 'o')\n    })\n\n    it('queries inside shadowdom, and pierces to find nearest controller', () => {\n      const div = document.createElement('div')\n      const shadow = div.attachShadow({mode: 'open'})\n      const span = document.createElement('span')\n      span.setAttribute('data-tagtest', 'div.p.q.r')\n      shadow.append(span)\n      observeElementForTags(shadow)\n      expect(testParse).to.be.calledWithExactly('div.p.q.r')\n      expect(testFound).to.be.calledWithExactly(span, div, 'data-tagtest', 'p', 'q', 'r')\n    })\n\n    describe('mutations', () => {\n      it('calls parse+found on attributes that change', async () => {\n        instance.setAttribute('data-tagtest', 'section.s.t.u not.v.w.x')\n        await Promise.resolve()\n        expect(testParse).to.be.calledWithExactly('section.s.t.u')\n        expect(testParse).to.be.calledWithExactly('not.v.w.x')\n        expect(testFound).to.be.calledWithExactly(instance, instance, 'data-tagtest', 's', 't', 'u')\n        expect(testFound).to.not.be.calledWithMatch(match.any, match.any, 'data-tagtest', 'v', 'w', 'x')\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/target.ts",
    "content": "import {expect, fixture, html} from '@open-wc/testing'\nimport {target, targets} from '../src/target.js'\nimport {controller} from '../src/controller.js'\n\ndescribe('Targetable', () => {\n  @controller\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  class TargetTestElement extends HTMLElement {\n    @target foo!: Element\n    bar = 'hello'\n    @target baz!: Element\n    @target qux!: Element\n    @target shadow!: Element\n\n    @target bing!: Element\n    @targets foos!: Element[]\n    bars = 'hello'\n    @target quxs!: Element[]\n    @target shadows!: Element[]\n  }\n\n  let instance: HTMLElement\n  beforeEach(async () => {\n    instance = await fixture(html`<target-test>\n      <target-test>\n        <div id=\"el1\" data-target=\"target-test.barfoo target-test.foobar\"></div>\n        <div id=\"el2\" data-target=\"target-test.foo\" data-targets=\"target-test.foos\"></div>\n        <div id=\"el3\" data-target=\"target-test.bing\"></div>\n      </target-test>\n      <div id=\"el4\" data-target=\"target-test.foo\" data-targets=\"target-test.foos\"></div>\n      <div id=\"el5\" data-target=\"target-test.baz\" data-targets=\"target-test.foos\"></div>\n      <div id=\"el6\" data-target=\"target-test.bar target-test.bing\"></div>\n      <div id=\"el7\" data-target=\"target-test.bazbaz\"></div>\n      <div id=\"el8\" data-target=\"other-target.qux target-test.qux\"></div>\n    </target-test>`)\n  })\n\n  describe('target', () => {\n    it('returns the first element where closest tag is the controller', async () => {\n      expect(instance).to.have.property('foo').exist.with.attribute('id', 'el4')\n      expect(instance.querySelector('target-test')).to.have.property('foo').exist.with.attribute('id', 'el2')\n    })\n\n    it('does not assign to non-target decorated properties', async () => {\n      expect(instance).to.have.property('bar', 'hello')\n    })\n\n    it('returns the first element that has the exact target name', async () => {\n      expect(instance).to.have.property('baz').exist.with.attribute('id', 'el5')\n    })\n\n    it('returns target when there are mutliple target values', async () => {\n      expect(instance).to.have.property('bing').exist.with.attribute('id', 'el6')\n    })\n\n    it('returns targets when there are mutliple target values with different controllers', async () => {\n      expect(instance).to.have.property('qux').exist.with.attribute('id', 'el8')\n    })\n\n    it('returns targets from the shadowRoot, if available', async () => {\n      instance.attachShadow({mode: 'open'})\n      const el = document.createElement('div')\n      el.setAttribute('data-target', 'target-test.shadow')\n      instance.shadowRoot!.appendChild(el)\n      expect(instance).to.have.property('shadow', el)\n    })\n\n    it('prioritises shadowRoot targets over others', async () => {\n      instance.attachShadow({mode: 'open'})\n      const shadowEl = document.createElement('div')\n      shadowEl.setAttribute('data-target', 'target-test.foo')\n      instance.shadowRoot!.appendChild(shadowEl)\n      expect(instance).to.have.property('foo', shadowEl)\n    })\n  })\n\n  describe('targets', () => {\n    it('returns all elements where closest tag is the controller', async () => {\n      expect(instance).to.have.property('foos').with.lengthOf(2)\n      expect(instance).to.have.nested.property('foos[0]').with.attribute('id', 'el4')\n      expect(instance).to.have.nested.property('foos[1]').with.attribute('id', 'el5')\n    })\n\n    it('returns all elements inside a shadow root', async () => {\n      instance.attachShadow({mode: 'open'})\n      const els = [document.createElement('div'), document.createElement('div'), document.createElement('div')]\n      for (const el of els) el.setAttribute('data-targets', 'target-test.foos')\n      instance.shadowRoot!.append(...els)\n\n      expect(instance).to.have.property('foos').with.lengthOf(5)\n      expect(instance).to.have.nested.property('foos[0]', els[0])\n      expect(instance).to.have.nested.property('foos[1]', els[1])\n      expect(instance).to.have.nested.property('foos[2]', els[2])\n      expect(instance).to.have.nested.property('foos[3]').with.attribute('id', 'el4')\n      expect(instance).to.have.nested.property('foos[4]').with.attribute('id', 'el5')\n    })\n  })\n})\n"
  },
  {
    "path": "tsconfig.build.json",
    "content": "{\n  \"exclude\": [\"test\"],\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"outDir\": \"./lib\",\n    \"noEmit\": false\n  }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"include\": [\"src\", \"test\"],\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"esModuleInterop\": true,\n    \"experimentalDecorators\": true,\n    \"lib\": [\"es2020\", \"dom\", \"dom.iterable\"],\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"node\",\n    \"noEmit\": true,\n    \"sourceMap\": true,\n    \"strict\": true,\n    \"target\": \"ES2020\"\n  }\n}\n"
  },
  {
    "path": "web-test-runner.config.js",
    "content": "import {esbuildPlugin} from '@web/dev-server-esbuild'\n\nexport default {\n  files: ['test/*'],\n  nodeResolve: true,\n  concurrency: 1,\n  testsFinishTimeout: 30000,\n  plugins: [esbuildPlugin({ts: true, target: 'es2020'})],\n  filterBrowserLogs: log => !log.args.some(arg => typeof arg === 'string' && arg.includes('Lit is in dev mode'))\n}\n"
  }
]