diff --git a/.envrc b/.envrc
index 8ebe67ac3..bccbea9d7 100644
--- a/.envrc
+++ b/.envrc
@@ -1,2 +1,9 @@
-use flake
-eval "$shellHook"
\ No newline at end of file
+if ! type "nix" > /dev/null; then
+    use nix -A default
+    eval "$shellHook"
+    use nix -A ghcjs
+else
+    use flake .#default
+    eval "$shellHook"
+    use flake .#ghcjs
+fi
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..b471bffe2
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+rzk/grammar/Syntax.cf linguist-language=EBNF linguist-detectable=true
+rzk/src/Language/Rzk/Syntax/* linguist-generated=true
+docs/** linguist-documentation=true
diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml
deleted file mode 100644
index fe62bfea1..000000000
--- a/.github/workflows/binaries.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-# Inspired by https://github.com/JustusAdam/create-haskell-binaries-with-actions
-
-name: Create Release Binaries
-on:
-  release:
-    types: [published]
-
-permissions:
-  contents: write
-
-jobs:
-  build:
-    runs-on: ${{ matrix.os }}
-    strategy:
-      matrix:
-        os: [ubuntu-latest, windows-latest, macos-latest]
-
-    steps:
-      - uses: actions/checkout@v3
-
-      - name: Cache Stack files
-        uses: actions/cache@v3
-        env:
-          cache-name: cache-tools-and-libraries
-        with:
-          path: ~/.stack
-          key: ${{ runner.os }}-ca-${{ env.cache-name }}-${{ hashFiles('**/stack.yaml.lock') }}
-          restore-keys: |
-            ${{ runner.os }}-ca-${{ env.cache-name }}-
-            ${{ runner.os }}-ca-
-            ${{ runner.os }}-
-
-      #    - name: πŸ”¨ Install BNFC, alex and happy (with Stack)
-      #      run: |
-      #        stack install alex happy BNFC
-      #
-      #    - name: πŸ”¨ Generate Syntax files using BNFC
-      #      run: |
-      #        cd rzk/ && (make && make clean; cd ../)
-
-      - name: πŸ”¨ Remove rzk.cabal, lexer and parser generator files
-        run: |
-          rm rzk/src/Language/Rzk/Syntax/Lex.x
-          rm rzk/src/Language/Rzk/Syntax/Par.y
-          rm rzk/rzk.cabal
-
-      - name: πŸ”¨ Build the project
-        run: stack build
-
-      - name: Tar and strip the binary
-        run: |
-          mkdir -p prepared_binaries/
-          cd prepared_binaries/
-          export PROGRAM=rzk
-          cp `stack exec -- which $PROGRAM` .
-          tar -cavf program.tar.gz *
-        shell: bash
-
-      - name: πŸš€ Upload assets
-        id: upload-release-asset
-        uses: actions/upload-release-asset@v1
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        with:
-          upload_url: ${{ github.event.release.upload_url }}
-          asset_path: ./prepared_binaries/program.tar.gz
-          asset_name: rzk-${{ github.ref_name }}-${{ runner.os }}-${{ runner.arch }}.tar.gz
-          asset_content_type: application/tar.gz
diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
deleted file mode 100644
index 194fe51af..000000000
--- a/.github/workflows/build-test.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: Build and test with GHC
-
-# Controls when the workflow will run
-on:
-  # Triggers the workflow on push or pull request events but only for the main branch
-  push:
-    paths:
-      - .github/workflows/build-test.yml
-      - rzk/**
-      - stack.yaml
-
-  # Allows you to run this workflow manually from the Actions tab
-  workflow_dispatch:
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
-  # This workflow contains a single job called "build"
-  build-test:
-    # The type of runner that the job will run on
-    runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
-    steps:
-      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
-      - name: πŸ“₯ Checkout repository
-        uses: actions/checkout@v3
-
-      - name: 🧰 Setup Stack
-        uses: haskell/actions/setup@v1
-        with:
-          enable-stack: true
-
-      - name: πŸ’Ύ Cache .stack/
-        uses: actions/cache@v2
-        with:
-          path: |
-            .stack
-          key: ${{ runner.os }}-${{ hashFiles('stack.yaml.lock', 'rzk.cabal') }}-stack
-
-      - name: πŸ”¨ Install BNFC, alex and happy (with Stack)
-        run: |
-          stack install alex happy BNFC
-      - name: πŸ”¨ Generate Syntax files using BNFC
-        run: |
-          cd rzk/ && (make && make clean; cd ../)
-
-      - name: πŸ”¨ Build dependencies (with Stack)
-        run: |
-          stack build --only-dependencies
-
-      - name: πŸ”¨ Build and test (with Stack)
-        run: |
-          stack test
diff --git a/.github/workflows/ghc.yml b/.github/workflows/ghc.yml
new file mode 100644
index 000000000..bf96b76f3
--- /dev/null
+++ b/.github/workflows/ghc.yml
@@ -0,0 +1,106 @@
+name: GHC (build, test, haddock)
+
+# Controls when the workflow will run
+on:
+  push:
+    branches: [main, develop]
+    tags: [v*]
+    paths:
+      - .github/workflows/ghcjs.yml
+      - rzk/**
+      - stack.yaml
+      - rzk.yaml
+      - "**/*.rzk.md"
+      - "**/*.rzk"
+      - "**/*.rzk.tex"
+  pull_request:
+    branches: [develop]
+    paths:
+      - .github/workflows/ghcjs.yml
+      - rzk/**
+      - stack.yaml
+      - rzk.yaml
+      - "**/*.rzk.md"
+      - "**/*.rzk"
+      - "**/*.rzk.tex"
+
+  # Allows you to run this workflow manually from the Actions tab
+  workflow_dispatch:
+
+permissions:
+  contents: write
+
+jobs:
+  build:
+    name: "Build and test with GHC"
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: πŸ“₯ Checkout repository
+        uses: actions/checkout@v3
+
+      - name: 🧰 Setup Stack
+        uses: freckle/stack-action@v4
+
+      - name: Tar and strip the binary
+        run: |
+          mkdir -p bin/
+          cp $(stack exec -- which rzk) bin/.
+          tar -cvzf rzk-bin.tar.gz bin/
+
+      - name: Upload rzk binary as Artifact
+        uses: actions/upload-artifact@v3
+        with:
+          path: rzk-bin.tar.gz
+          name: rzk-bin
+          if-no-files-found: error
+
+  haddock:
+    needs: [build]
+    if: ${{ github.ref_name == 'develop' }}
+    name: "Build and upload Haddock documentation (develop)"
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: πŸ“₯ Checkout repository
+        uses: actions/checkout@v3
+
+      - name: 🧰 Setup Stack
+        uses: freckle/stack-action@v4
+
+      - name: πŸ”¨ Build Haddock Documentation (with Stack)
+        run: |
+          stack haddock
+          mkdir -p dist/haddock
+          mv $(stack path --local-doc-root)/* dist/haddock
+
+      - name: πŸš€ Publish Haddock Documentation
+        uses: JamesIves/github-pages-deploy-action@v4
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          folder: dist/haddock
+          target-folder: haddock
+          single-commit: true
+
+  rzk:
+    needs: [build]
+    name: "Check Rzk formalizations"
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: πŸ“₯ Checkout repository
+        uses: actions/checkout@v3
+
+      - name: πŸ“₯ Download rzk
+        id: download
+        uses: actions/download-artifact@v3
+        with:
+          name: rzk-bin
+
+      - name: Unpack rzk-bin.tar.gz
+        run: |
+          tar xzf ${{ steps.download.outputs.download-path}}/rzk-bin.tar.gz
+
+      - name: Check Rzk files
+        run: ./bin/rzk typecheck
+        shell: bash
diff --git a/.github/workflows/ghcjs.yml b/.github/workflows/ghcjs.yml
index a36bccdd7..12369d05c 100644
--- a/.github/workflows/ghcjs.yml
+++ b/.github/workflows/ghcjs.yml
@@ -1,4 +1,4 @@
-name: Build with GHCJS and Deploy to GitHub Pages
+name: GHCJS (build and deploy Rzk playground)
 
 on:
   push:
@@ -7,14 +7,19 @@ on:
     paths:
       - .github/workflows/ghcjs.yml
       - rzk/**
-      - try-rzk/**
+      - rzk-js/**
+      - rzk-playground/**
       - stack.yaml
+      - "**/*.nix"
   pull_request:
-    branches: [main, develop]
+    branches: [develop]
     paths:
+      - .github/workflows/ghcjs.yml
       - rzk/**
-      - try-rzk/**
+      - rzk-js/**
+      - rzk-playground/**
       - stack.yaml
+      - "**/*.nix"
 
   workflow_dispatch: # allow triggering this workflow manually
 
@@ -22,13 +27,14 @@ permissions:
   contents: write
 
 jobs:
-  build-and-deploy:
+  build-and-deploy-with-ghcjs:
+    name: "Build with GHCJS (and deploy Rzk playground)"
     runs-on: ubuntu-latest
     steps:
       - name: πŸ“₯ Checkout repository
         uses: actions/checkout@v3
 
-      - name: 🧰 Setup nix
+      - name: ❄️ Install Nix
         uses: nixbuild/nix-quick-install-action@v25
         with:
           nix_conf: |
@@ -36,36 +42,52 @@ jobs:
             trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= miso-haskell.cachix.org-1:6N2DooyFlZOHUfJtAx1Q09H0P5XXYzoxxQYiwn6W1e8=
             keep-outputs = true
 
-      - name: Restore and cache Nix store
-        uses: nix-community/cache-nix-action@v1
+      - name: πŸ‘ Restore and Cache Nix store
+        uses: nix-community/cache-nix-action@v4
         with:
-          key: ${{ runner.os }}-nix-${{ hashfiles('./flake.nix', './flake.lock', '.github/workflows/ghcjs.yml') }}
+          key: ${{ runner.os }}-nix-${{ hashfiles('./flake.nix', './flake.lock', '.github/workflows/ghcjs.yml', './rzk/rzk.cabal') }}
           restore-keys: |
-            ${{ runner.os }}-nix-${{ hashfiles('./flake.nix', './flake.lock', '.github/workflows/ghcjs.yml') }}
+            ${{ runner.os }}-nix-${{ hashfiles('./flake.nix', './flake.lock', '.github/workflows/ghcjs.yml', './rzk/rzk.cabal') }}
             ${{ runner.os }}-nix-
+          gc-linux: true
+          gc-max-store-size-linux: 7000000000
+          purge: true
+          purge-created-max-age: 1209600
+
+      - name: πŸ‘ Restore and Cache NextJS cache
+        uses: actions/cache@v3
+        with:
+          key: ${{ runner.os }}-next-${{ hashFiles('**/package-lock.json') }}
+          restore-keys: |
+            ${{ runner.os }}-next-
+          path: |
+            ~/.npm
+            rzk-playground/.next/cache
 
       - name: πŸ”¨ Remove lexer and parser generator files
         run: |
           rm -f rzk/src/Language/Rzk/Syntax/Lex.x
           rm -f rzk/src/Language/Rzk/Syntax/Par.y
 
-      - name: πŸ”¨ Build GHCJS version with Nix
-        run: |
-          nix build .#try-rzk || (nix log /nix/store/*-rzk-0.6.3.drv ; false)
+      # Uncomment to debug this job
+      # - name: Setup tmate session
+      #   uses: mxschmitt/action-tmate@v3
 
-      - name: πŸ”¨ Collect build artifacts
+      - name: πŸ”¨ Build Playground
+        env:
+          BASEPATH: /${{ github.event.repository.name }}/${{ github.ref_name }}/playground
         run: |
-          mkdir -p dist/result/bin
-          cp -r result/bin/try-rzk.jsexe/ dist/result/bin/.
-          chmod -R +w dist/
-          cp try-rzk/index.html dist/.
+          nix run .#release-rzk-playground
+
+      - name: πŸ”¨ Save flake from garbage collection
+        run: nix run .#save-flake
 
       - name: 'πŸš€ Publish JS "binaries" (${{ github.ref_name }})'
         if: ${{ github.ref_name != 'main' && github.event_name == 'push' }}
         uses: JamesIves/github-pages-deploy-action@v4
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
-          folder: dist
+          folder: rzk-playground-release
           target-folder: ${{ github.ref_name }}/playground
           clean: false
           single-commit: true
@@ -75,7 +97,7 @@ jobs:
         uses: JamesIves/github-pages-deploy-action@v4
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
-          folder: dist
+          folder: rzk-playground-release
           target-folder: playground
           clean: false
           single-commit: true
diff --git a/.github/workflows/hackage.yml b/.github/workflows/hackage.yml
deleted file mode 100644
index fe426ba6a..000000000
--- a/.github/workflows/hackage.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-name: Upload on Hackage
-on:
-  release:
-    types: [published]
-
-jobs:
-  hackage:
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/checkout@v3
-
-    - name: Cache Stack files
-      uses: actions/cache@v3
-      env:
-        cache-name: cache-tools-and-libraries
-      with:
-        path: ~/.stack
-        key: ${{ runner.os }}-ca-${{ env.cache-name }}-${{ hashFiles('**/stack.yaml.lock') }}
-        restore-keys: |
-          ${{ runner.os }}-ca-${{ env.cache-name }}-
-          ${{ runner.os }}-ca-
-          ${{ runner.os }}-
-
-#    - name: πŸ”¨ Install BNFC, alex and happy (with Stack)
-#      run: |
-#        stack install alex happy BNFC
-#
-#    - name: πŸ”¨ Generate Syntax files using BNFC
-#      run: |
-#        cd rzk/ && (make && make clean; cd ../)
-
-    - name: πŸ”¨ Remove rzk.cabal, lexer and parser generator files
-      run: |
-        rm rzk/src/Language/Rzk/Syntax/Lex.x
-        rm rzk/src/Language/Rzk/Syntax/Par.y
-        rm rzk/rzk.cabal
-
-    - name: πŸ”¨ Build the project
-      run: stack build
-
-    - name: "Generate package dist tarball"
-      run: stack sdist --tar-dir packages/
-
-    - name: πŸš€ Upload on Hackage
-      uses: haskell-actions/hackage-publish@v1
-      with:
-        hackageToken: ${{ secrets.HACKAGE_AUTH_TOKEN }}
-        packagesPath: packages
-        publish: false
-
-
-
-
-
-
-
-
diff --git a/.github/workflows/haddock.yml b/.github/workflows/haddock.yml
deleted file mode 100644
index f809dff19..000000000
--- a/.github/workflows/haddock.yml
+++ /dev/null
@@ -1,65 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: Build and Deploy Haddock to GitHub Pages
-
-# Controls when the workflow will run
-on:
-  # Triggers the workflow on push or pull request events but only for the main branch
-  push:
-    branches: [ main ]
-    paths:
-      - .github/workflows/haddock.yml
-      - rzk/**
-      - stack.yaml
-
-  # Allows you to run this workflow manually from the Actions tab
-  workflow_dispatch:
-
-permissions:
-  contents: write
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
-  # This workflow contains a single job called "build"
-  haddock:
-    # The type of runner that the job will run on
-    runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
-    steps:
-      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
-      - name: πŸ“₯ Checkout repository
-        uses: actions/checkout@v3
-
-      - name: 🧰 Setup Stack
-        uses: haskell/actions/setup@v1
-        with:
-          enable-stack: true
-
-      - name: πŸ’Ύ Cache .stack/
-        uses: actions/cache@v2
-        with:
-          path: |
-            .stack
-          key: ${{ runner.os }}-${{ hashFiles('stack.yaml.lock', 'rzk.cabal') }}-stack
-
-      - name: πŸ”¨ Install BNFC, alex and happy (with Stack)
-        run: |
-          stack install alex happy BNFC
-      - name: πŸ”¨ Generate Syntax files using BNFC
-        run: |
-          cd rzk/ && (make && make clean; cd ../)
-
-      - name: πŸ”¨ Build Haddock Documentation (with Stack)
-        run: |
-          stack haddock
-          mkdir -p dist/haddock
-          mv $(stack path --local-doc-root)/* dist/haddock
-
-      - name: πŸš€ Publish Haddock Documentation
-        uses: JamesIves/github-pages-deploy-action@v4
-        with:
-          token: ${{ secrets.GITHUB_TOKEN }}
-          folder: dist/haddock
-          target-folder: haddock
-          single-commit: true
diff --git a/.github/workflows/mkdocs.yml b/.github/workflows/mkdocs.yml
index ff55a0507..5aa5f4b3d 100644
--- a/.github/workflows/mkdocs.yml
+++ b/.github/workflows/mkdocs.yml
@@ -1,9 +1,9 @@
-name: Build and Deploy MkDocs to GitHub Pages
+name: MKDocs
 
 on:
   push:
-    branches: [ develop ]
-    tags: [ v* ]
+    branches: [develop]
+    tags: [v*]
     paths:
       - .github/workflows/mkdocs.yml
       - docs/**
@@ -15,6 +15,7 @@ permissions:
 
 jobs:
   mkdocs:
+    name: "Build and Deploy MkDocs to GitHub Pages"
     runs-on: ubuntu-latest
     steps:
       - name: πŸ“₯ Checkout repository
@@ -25,8 +26,8 @@ jobs:
       - name: 🧰 Set up Python
         uses: actions/setup-python@v4
         with:
-          python-version: '3.9'
-          cache: 'pip' # caching pip dependencies
+          python-version: "3.9"
+          cache: "pip" # caching pip dependencies
 
       - name: πŸ”¨ Install rzk proof assistant
         uses: jaxxstorm/action-install-gh-release@v1.10.0
@@ -53,4 +54,3 @@ jobs:
         if: ${{ github.ref_name == 'develop' }}
         run: |
           mike deploy --rebase --push --config-file docs/mkdocs.yml ${{ github.ref_name }}
-
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 000000000..3be2af0fb
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,65 @@
+name: Release
+on:
+  release:
+    types: [published]
+
+permissions:
+  contents: write
+
+jobs:
+  hackage:
+    name: "Upload a new candidate on Hackage"
+    runs-on: ubuntu-latest
+    steps:
+      - name: πŸ“₯ Checkout repository
+        uses: actions/checkout@v3
+
+      - name: 🧰 Setup Stack
+        uses: freckle/stack-action@v4
+        with:
+          fast: false
+
+      - name: πŸ”¨ Generate package dist tarball
+        run: stack sdist --tar-dir packages/
+
+      - name: πŸš€ Upload on Hackage
+        uses: haskell-actions/hackage-publish@v1
+        with:
+          hackageToken: ${{ secrets.HACKAGE_AUTH_TOKEN }}
+          packagesPath: packages
+          publish: false
+
+  binaries:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-latest, windows-latest, macos-latest]
+
+    steps:
+      - name: πŸ“₯ Checkout repository
+        uses: actions/checkout@v3
+
+      - name: 🧰 Setup Stack
+        uses: freckle/stack-action@v4
+        with:
+          fast: false
+
+      - name: Tar and strip the binary
+        run: |
+          mkdir -p prepared_binaries/
+          cd prepared_binaries/
+          export PROGRAM=rzk
+          cp `stack exec -- which $PROGRAM` .
+          tar -cavf program.tar.gz *
+        shell: bash
+
+      - name: πŸš€ Upload assets
+        id: upload-release-asset
+        uses: actions/upload-release-asset@v1
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          upload_url: ${{ github.event.release.upload_url }}
+          asset_path: ./prepared_binaries/program.tar.gz
+          asset_name: rzk-${{ github.ref_name }}-${{ runner.os }}-${{ runner.arch }}.tar.gz
+          asset_content_type: application/tar.gz
diff --git a/.gitignore b/.gitignore
index e943c8b5b..27563190a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,5 @@ __pycache__
 *.fdb_latexmk
 *.fls
 *.log
-rzk/doc/
\ No newline at end of file
+rzk/doc/
+/rzk-playground-release
\ No newline at end of file
diff --git a/CITATION.cff b/CITATION.cff
index 94eb5862c..7dd423d6c 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -3,6 +3,6 @@ authors:
 - family-names: Kudasov
   given-names: Nikolai
   orcid: "https://orcid.org/0000-0001-6572-7292"
-title: "rzk: a prototype proof assistant for synthetic $\\infty$-categories"
-version: 0.5.2
+title: "Rzk: a  proof assistant for synthetic $\\infty$-categories"
+version: 0.6.5
 url: "https://github.com/rzk-lang/rzk"
diff --git a/README.md b/README.md
index 1b4958718..5a0ce5a32 100644
--- a/README.md
+++ b/README.md
@@ -10,32 +10,36 @@ An experimental proof assistant for synthetic ∞-categories.
 
 ## About this project
 
-This project has started with the idea of bringing Riehl and Shulman's 2017 paper [1] to "life" by implementing a proof assistant based on their type theory with shapes. Currently an early prototype with an [online playground](https://rzk-lang.github.io/rzk/) is available. The current implementation is capable of checking various formalisations. Perhaps, the largest formalisations are available in two related projects: https://github.com/fizruk/sHoTT and https://github.com/emilyriehl/yoneda. `sHoTT` project (originally a fork of the yoneda project) aims to cover more formalisations in simplicial HoTT and ∞-categories, while `yoneda` project aims to compare different formalisations of the Yoneda lemma.
+This project has started with the idea of bringing Riehl and Shulman's 2017 paper [1] to "life" by implementing a proof assistant based on their type theory with shapes. Currently an early prototype with an [online playground](https://rzk-lang.github.io/rzk/develop/playground/) is available. The current implementation is capable of checking various formalisations. Perhaps, the largest formalisations are available in two related projects: <https://rzk-lang.github.com/sHoTT> and <https://github.com/emilyriehl/yoneda>. `sHoTT` project (originally a fork of the yoneda project) aims to cover more formalisations in simplicial HoTT and ∞-categories, while `yoneda` project aims to compare different formalisations of the Yoneda lemma.
 
 Internally, `rzk` uses a version of second-order abstract syntax allowing relatively straightforward handling of binders (such as lambda abstraction). In the future, `rzk` aims to support dependent type inference relying on E-unification for second-order abstract syntax [2].
 Using such representation is motivated by automatic handling of binders and easily automated boilerplate code. The idea is that this should keep the implementation of `rzk` relatively small and less error-prone than some of the existing approaches to implementation of dependent type checkers.
 
-An important part of `rzk` is a tope layer solver, which is essentially a theorem prover for a part of the type theory. A related project, dedicated just to that part is available at https://github.com/fizruk/simple-topes. `simple-topes` supports used-defined cubes, topes, and tope layer axioms. Once stable, `simple-topes` will be merged into `rzk`, expanding the proof assistant to the type theory with shapes, allowing formalisations for (variants of) cubical, globular, and other geometric versions of HoTT.
+An important part of `rzk` is a tope layer solver, which is essentially a theorem prover for a part of the type theory. A related project, dedicated just to that part is available at <https://github.com/fizruk/simple-topes>. `simple-topes` supports used-defined cubes, topes, and tope layer axioms. Once stable, `simple-topes` will be merged into `rzk`, expanding the proof assistant to the type theory with shapes, allowing formalisations for (variants of) cubical, globular, and other geometric versions of HoTT.
+
+See the list of contributors at [docs/docs/CONTRIBUTORS.md](docs/docs/CONTRIBUTORS.md).
 
 ## How to use `rzk`
 
-For relatively small single-file formalisations, you can use the online playground at https://rzk-lang.github.io/rzk/playground.html
+For relatively small single-file formalisations, you can use the online playground at <https://rzk-lang.github.io/rzk/develop/playground>
 
 However, for larger and multi-file formalisations you should install a version of `rzk` locally:
 
 - You can install the latest "stable" version of `rzk` from Hackage:
+
   ```sh
   cabal install rzk
   ```
-  
+
 - You can install the latest "development" version of `rzk` from the [`develop` branch](https://github.com/rzk-lang/rzk/tree/develop) of this repository:
+
   ```sh
   git clone https://github.com/rzk-lang/rzk.git
   cd rzk
   git checkout develop
   stack build && stack install
   ```
-  
+
 ### VS Code
 
 There exists a [VS Code extension for `rzk`](https://marketplace.visualstudio.com/items?itemName=NikolaiKudasovfizruk.rzk-1-experimental-highlighting) available on the Marketplace. The extension supports basic syntax highlighting, but more features may come in the future.
@@ -50,7 +54,7 @@ rzk typecheck first.rzk second.rzk third.rzk
 
 A proper support for inter-file dependencies will be implemented in the future. Until then, it is recommented to start names of files with a number, ensuring correct order when using a wildcard (`*`). For example:
 
-```
+```console
 .
 β”œβ”€β”€ 0-common.md
 β”œβ”€β”€ 1-paths.md
@@ -85,21 +89,21 @@ Now, you can build and serve the documentation locally by running
 mkdocs serve --config-file docs/mkdocs.yml
 ```
 
-The (locally built) documentation should be available at http://127.0.0.1:8000
+The (locally built) documentation should be available at <http://127.0.0.1:8000>
 
 The pages of the documentation are the `*.md` files in [docs/docs](docs/docs) directory and its subdirectories.
 To add a new page, you can create a new `*.md` file and add it to the navigation by modifying [docs/mkdocs.yml](docs/mkdocs.yml).
 
-### Development
+## Development
 
-The project is developed with both Stack and Nix (for GHCJS version).
+The project is developed with both [stack](https://docs.haskellstack.org/en/stable/README/) and [nix](https://nixos.org/manual/nix/unstable/introduction).
 
-#### Building with GHC
+## Develop `rzk` with stack
 
-For quick local development and testing it is recommended to work with a GHC version, using [Stack tool](https://docs.haskellstack.org/en/stable/README/). Clone this project and simply run `stack build`:
+For quick local development and testing it is recommended to work with a GHC version, using the `stack` tool. Clone this project and run `stack build`:
 
 ```sh
-git clone git@github.com:rzk-lang/rzk.git
+git clone https://github.com/rzk-lang/rzk.git
 cd rzk
 stack build
 ```
@@ -110,96 +114,192 @@ The build provides an executable `rzk` which can be used to typecheck files:
 stack exec -- rzk typecheck FILE
 ```
 
-#### Building with GHCJS
+## Develop with `nix`
 
-`try-rzk` package is designed to be compiled using GHCJS for an in-browser version of the proof assistant. To build this package you need to use Nix. It is recommended that you use Cachix to avoid recompiling lots of dependencies:
+1. Install `nix`:
 
-```sh
-# Install Nix
-curl https://nixos.org/nix/install | sh
-# (optionally) Install Cachix
-nix-env -iA cachix -f https://cachix.org/api/v1/install
-# (optionally) Use cached miso from Cachix
-cachix use miso-haskell
+   ```console
+   sh <(curl -L https://nixos.org/nix/install) --no-daemon
+   ```
+
+2. (Optionally) Permanently [enable nix flakes](https://nixos.wiki/wiki/Flakes#Permanent) to use faster and more convenient experimental (but quite stable) commands.
+3. Use `cachix` to avoid building multiple dependencies:
+   1. Without flakes: `nix-shell -p cachix --command 'cachix use miso-haskell'`
+   2. With flakes: `nix shell nixpkgs#cachix -c cachix use miso-haskell`
+4. (Optionally) Install [direnv](https://direnv.net/#basic-installation) to start the `devShell` when you enter the repository directory.
+   1. The `nix-direnv` repo shows [installation options](https://github.com/nix-community/nix-direnv#installation).
+5. (Optionally) If you use VS Code, you can install `mkhl.direnv` extension that loads `direnv` environments.
+
+6. Clone this repository and enter it
+
+   ```console
+   git clone git@github.com:rzk-lang/rzk.git
+   cd rzk
+   ```
+
+7. Run `direnv allow` in the repository root.
+8. Use `cabal` for development.
+   - `cabal` performs incremental builds meaning it will build only the parts that are changed. This is quite fast.
+   - `nix` will rebuild the package `A` when its dependency `B` changes. Moreover, `nix` will rebuild all packages that are dependencies of `A` and that depend on `B`. This is much slower than incremental builds.
+   - So, use `nix` for setting up the environment with necessary tools that don't need rebuilds.
+9. The following sections provide commands to build and run packages. They should be executed from the root directory of this repository.
+10. The commands `nix-shell`, `nix shell`, and `nix develop` start shells with necessary tools.
+    Run subsequent commands from code blocks in these shells.
+
+## Permanently install `rzk`
+
+### without flakes
+
+```console
+nix-env -iA default -f default.nix
+rzk version
 ```
 
-Clone the repository, enter `try-rzk` directory and use `nix-build`:
-```sh
-git clone git@github.com:rzk-lang/rzk.git
-cd rzk/try-rzk
-nix-build
+### with flakes
+
+```console
+nix profile install
+rzk version
 ```
 
-Now open `playground.html` to see the result. Note that if local GHCJS build is unavailable, `playground.html` will use the [JS file from GitHub Pages](https://rzk-lang.github.io/rzk/v0.1.0/result/bin/try-rzk.jsexe/all.js) as a fallback.
+Also see [nix profile remove](https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-profile-remove).
 
-##### Flake
+## Develop `rzk`
 
-The flake in this repository allows to build `try-rzk` incrementally and reproducibly.
+`nix-shell` and `nix develop` start shells with `cabal`, `ghc` with packages, `hpack`, `haskell-language-server`.
 
-1. Install `Nix` via single-user [installation](https://nixos.org/download.html#download-nix):
+### without flakes
 
-   1. Run script
+#### `cabal`
 
-     ```sh
-     sh <(curl -L https://nixos.org/nix/install) --no-daemon
-     ```
+```console
+nix-shell -A default
+# (Optionally) build
+cabal build rzk
+cabal run rzk -- version
+```
+
+#### `nix-build`
 
-   1. Permanently [enable](https://nixos.wiki/wiki/Flakes#Permanent) flakes
+```console
+nix-build -A default
+./result/bin/rzk version
+```
 
-1. Enter the `devShell` with `GHC` (not `GHCJS`). Answer `y` to `Nix` prompts to use binary caches.
+### with flakes
 
-    ```sh
-    nix develop
-    ```
+#### `cabal`
 
-1. The shell provides `ghc`, `haskell-language-server`, `cabal-install`, `hpack`.
+```console
+nix develop
+# (Optionally) build
+cabal build rzk
+cabal run rzk -- version
+```
 
-1. (Optionally) Install [direnv](https://direnv.net/) to start the `devShell` when you enter the repository directory.
+#### `nix build`
 
-1. Build `rzk`.
+```console
+nix build
+./result/bin/rzk version
+```
 
-    ```sh
-    cabal build
-    ```
+#### `nix run`
 
-1. Enter the `devShell` with `GHCJS`.
+```console
+nix run .# -- version
+```
 
-    ```sh
-    nix develop .#ghcjs
-    ```
+#### `nix shell`
 
-1. Build `try-rzk`. This may require ~10 GB of RAM.
+```console
+nix shell
+rzk version
+```
 
-    ```sh
-    cabal build --ghcjs
-    ```
+## Build `rzk-js`
 
-1. (Optionally) Build `rzk` via `Nix`. The resulting executable will be in `result/bin/rzk`.
+[rzk-js](./rzk-js/) is a wrapper around `rzk`.
+Building `rzk-js` via `GHCJS` produces a `JavaScript` script used in `rzk-playground`.
 
-    ```sh
-    nix build .#rzk
-    ```
+### without flakes
 
-1. (Optionally) Run `rzk` via `Nix`.
+#### `cabal`
 
-    ```sh
-    nix run .#rzk
-    ```
+```console
+nix-shell -A ghcjs
+build-rzk-js
+```
 
-1. (Optionally) Build `try-rzk` via `Nix`. This may require ~10 GB of RAM. The resulting executable will be in `try-rzk/result/bin/try-rzk.jsexe`.
+#### `nix-build`
 
-    ```sh
-    nix build .#try-rzk --out-link try-rzk/result
-    ```
+```console
+rm -rf rzk-playground/public/rzk.js
+nix-build -A rzk-js -o rzk-playground/public/rzk.js
+```
 
-1. Open the app in a browser.
+### with flakes
 
-    ```sh
-    firefox try-rzk/playground.html
-    ```
+#### `cabal`
+
+```console
+nix develop .#ghcjs
+build-rzk-js
+```
+
+#### `nix build`
+
+```console
+rm -rf rzk-playground/public/rzk.js
+nix build .#rzk-js -o rzk-playground/public/rzk.js
+```
+
+## `rzk-playground`
+
+[rzk-playground](./rzk-playground/) is a `JavaScript` application that combines an editor and basic `rzk` functionality.
+
+### Develop
+
+1. Load `nodejs`
+
+   - without flakes: `nix-shell`
+   - with flakes: `nix develop`
+
+1. Start a development server and open in a browser a link given by the server.
+
+   ```console
+   cd rzk-playground
+   npm run dev
+   ```
+
+### Release
+
+Build a static site to be hosted, e.g., on `GitHub Pages`.
+The `release-rzk-playground` script will write files to the `rzk-playground-release` directory.
+
+#### without flakes
+
+```console
+nix-shell -A release
+release-rzk-playground
+```
+
+#### with flakes
+
+##### `nix develop`
+
+```console
+nix develop .#release
+release-rzk-playground
+```
+
+##### `nix run`
+
+```console
+nix run .#release-rzk-playground
+```
 
 ## References
 
-1. Emily Riehl & Michael Shulman. A type theory for synthetic ∞-categories. Higher Structures 1(1), 147-224. 2017. https://arxiv.org/abs/1705.07442
-2. Nikolai Kudasov. E-unification for Second-Order Abstract Syntax. 2023. https://arxiv.org/abs/2302.05815
- 
+1. Emily Riehl & Michael Shulman. A type theory for synthetic ∞-categories. Higher Structures 1(1), 147-224. 2017. <https://arxiv.org/abs/1705.07442>
+2. Nikolai Kudasov. E-unification for Second-Order Abstract Syntax. 2023. <https://arxiv.org/abs/2302.05815>
diff --git a/cabal.project b/cabal.project
index eee6158d6..42f783dbd 100644
--- a/cabal.project
+++ b/cabal.project
@@ -1 +1 @@
-packages: rzk try-rzk
\ No newline at end of file
+packages: rzk rzk-js
\ No newline at end of file
diff --git a/default.nix b/default.nix
new file mode 100644
index 000000000..210377e4f
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,10 @@
+let t = (import
+  (
+    let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
+    fetchTarball {
+      url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
+      sha256 = lock.nodes.flake-compat.locked.narHash;
+    }
+  )
+  { src = ./.; }
+).defaultNix; in t // t.packages.${builtins.currentSystem}
\ No newline at end of file
diff --git a/docs/docs/CONTRIBUTORS.md b/docs/docs/CONTRIBUTORS.md
new file mode 100644
index 000000000..126c23cbc
--- /dev/null
+++ b/docs/docs/CONTRIBUTORS.md
@@ -0,0 +1,9 @@
+# List of contributors
+
+The following people have contributed to Rzk proof assistant:
+
+1. [Nikolai Kudasov](https://fizruk.github.io)
+2. [Abdelrahman Abounegm](https://github.com/aabounegm/) β€” contributed to the Rzk Language Server
+3. [Danila Danko](https://github.com/deemp) β€” helped set up Nix and Rzk playground
+
+You may see actual contributed commits in the [Contributors page on GitHub](https://github.com/rzk-lang/rzk/graphs/contributors).
diff --git a/docs/docs/examples/recId.rzk.md b/docs/docs/examples/recId.rzk.md
index 635a36a25..9637578ca 100644
--- a/docs/docs/examples/recId.rzk.md
+++ b/docs/docs/examples/recId.rzk.md
@@ -1,9 +1,9 @@
 # Tope disjuction elimination along identity paths
 
-\(\mathsf{rec}_{\lor}^{\psi,\phi}(a_\psi, a_\phi)\) (written `recOR(psi, phi, a_psi, a_phi)` in the code)
-is well-typed when \(a_\psi\) and \(a_\phi\) are _definitionally equal_ on \(\psi \land \phi\).
+\(\mathsf{rec}_{\lor}^{\ψ,\Ο†}(a_\ψ, a*\Ο†)\) (written `recOR(ψ, Ο†, a_psi, a_phi)` in the code)
+is well-typed when \(a*\ψ\) and \(a*\Ο†\) are \_definitionally equal* on \(\ψ \land \Ο†\).
 Sometimes this is too strong since many terms are not _definitionally_ equal, but only equal up to a path.
-Luckily, assuming relative function extensionality, we can define a weaker version of \(rec_{\lor}\) (`recOR`), which we call `recId`, that can work in presence of a witness of type \(\prod_{t : I \mid \psi \land \phi} a_\psi = a_\phi\).
+Luckily, assuming relative function extensionality, we can define a weaker version of \(rec*{\lor}\) (`recOR`), which we call `recId`, that can work in presence of a witness of type \(\prod*{t : I \mid \ψ \land \Ο†} a*\ψ = a*\Ο†\).
 
 ## Prerequisites
 
@@ -14,39 +14,39 @@ We begin by introducing common HoTT definitions:
 
 -- A is contractible there exists x : A such that for any y : A we have x = y.
 #define iscontr (A : U) : U
-  := βˆ‘ (a : A), (x : A) -> a =_{A} x
+  := Ξ£ (a : A), (x : A) β†’ a =_{A} x
 
 -- A is a proposition if for any x, y : A we have x = y
 #define isaprop (A : U) : U
-  := (x : A) -> (y : A) -> x =_{A} y
+  := (x : A) β†’ (y : A) β†’ x =_{A} y
 
 -- A is a set if for any x, y : A the type x =_{A} y is a proposition
 #define isaset (A : U) : U
-  := (x : A) -> (y : A) -> isaprop (x =_{A} y)
+  := (x : A) β†’ (y : A) β†’ isaprop (x =_{A} y)
 
 -- Non-dependent product of A and B
 #define prod (A : U) (B : U) : U
-  := βˆ‘ (x : A), B
+  := Ξ£ (x : A), B
 
--- A function f : A -> B is an equivalence
--- if there exists g : B -> A
+-- A function f : A β†’ B is an equivalence
+-- if there exists g : B β†’ A
 -- such that for all x : A we have g (f x) = x
 -- and for all y : B we have f (g y) = y
-#define isweq (A : U) (B : U) (f : A -> B) : U
-  := βˆ‘ (g : B -> A), prod ((x : A) -> g (f x) =_{A} x) ((y : B) -> f (g y) =_{B} y)
+#define isweq (A : U) (B : U) (f : A β†’ B) : U
+  := Ξ£ (g : B β†’ A), prod ((x : A) β†’ g (f x) =_{A} x) ((y : B) β†’ f (g y) =_{B} y)
 
 -- Equivalence of types A and B
 #define weq (A : U) (B : U) : U
-  := βˆ‘ (f : A -> B), isweq A B f
+  := Ξ£ (f : A β†’ B), isweq A B f
 
 -- Transport along a path
 #define transport
     (A : U)
-    (C : A -> U)
+    (C : A β†’ U)
     (x y : A)
     (p : x =_{A} y)
-    : C x -> C y
-  := \cx -> idJ(A, x, (\z q -> C z), cx, y, p)
+    : C x β†’ C y
+  := \ cx β†’ idJ(A, x, (\z q β†’ C z), cx, y, p)
 ```
 
 ## Relative function extensionality
@@ -57,29 +57,29 @@ We can now define relative function extensionality. There are several formulatio
 -- [RS17, Axiom 4.6] Relative function extensionality.
 #define relfunext : U
   := (I : CUBE)
-  -> (psi : I -> TOPE)
-  -> (phi : psi -> TOPE)
-  -> (A : psi -> U)
-  -> ((t : psi) -> iscontr (A t))
-  -> (a : (t : phi) -> A t)
-  -> (t : psi) -> A t [ phi t |-> a t]
+  β†’ (ψ : I β†’ TOPE)
+  β†’ (Ο† : ψ β†’ TOPE)
+  β†’ (A : ψ β†’ U)
+  β†’ ((t : ψ) β†’ iscontr (A t))
+  β†’ (a : (t : Ο†) β†’ A t)
+  β†’ (t : ψ) β†’ A t [ Ο† t ↦ a t]
 
 -- [RS17, Proposition 4.8] A (weaker) formulation of function extensionality.
 #define relfunext2 : U
   := (I : CUBE)
-  -> (psi : I -> TOPE)
-  -> (phi : psi -> TOPE)
-  -> (A : psi -> U)
-  -> (a : (t : phi) -> A t)
-  -> (f : (t : psi) -> A t [ phi t |-> a t ])
-  -> (g : (t : psi) -> A t [ phi t |-> a t ])
-  -> weq (f = g)
-         ((t : psi) -> (f t =_{A t} g t) [ phi t |-> refl ])
+  β†’ (ψ : I β†’ TOPE)
+  β†’ (Ο† : ψ β†’ TOPE)
+  β†’ (A : ψ β†’ U)
+  β†’ (a : (t : Ο†) β†’ A t)
+  β†’ (f : (t : ψ) β†’ A t [ Ο† t ↦ a t ])
+  β†’ (g : (t : ψ) β†’ A t [ Ο† t ↦ a t ])
+  β†’ weq (f = g)
+         ((t : ψ) β†’ (f t =_{A t} g t) [ Ο† t ↦ refl ])
 ```
 
 ## Construction of `recId`
 
-The idea is straightforward. We ask for a proof that `a = b` for all points in `psi /\ phi`. Then, by relative function extensionality (`relfunext2`), we can show that restrictions of `a` and `b` to `psi /\ phi` are equal. If we reformulate `a` as extension of its restriction, then we can `transport` such reformulation along the path connecting two restrictions and apply `recOR`.
+The idea is straightforward. We ask for a proof that `a = b` for all points in `ψ ∧ Ο†`. Then, by relative function extensionality (`relfunext2`), we can show that restrictions of `a` and `b` to `ψ ∧ Ο†` are equal. If we reformulate `a` as extension of its restriction, then we can `transport` such reformulation along the path connecting two restrictions and apply `recOR`.
 
 First, we define how to restrict an extension type to a subshape:
 
@@ -88,20 +88,20 @@ First, we define how to restrict an extension type to a subshape:
 
 #variable r : relfunext2
 #variable I : CUBE
-#variables psi phi : I -> TOPE
-#variable A : {t : I | psi t \/ phi t} -> U
+#variables ψ Ο† : I β†’ TOPE
+#variable A : (t : I | ψ t ∨ Ο† t) β†’ U
 
 -- Restrict extension type to a subshape.
 #define restrict_phi
-    (a : {t : I | phi t} -> A t)
-  : {t : I | psi t /\ phi t} -> A t
-  := \t -> a t
+    (a : (t : Ο†) β†’ A t)
+  : (t : I | ψ t ∧ Ο† t) β†’ A t
+  := \ t β†’ a t
 
 -- Restrict extension type to a subshape.
 #define restrict_psi
-    (a : {t : I | psi t} -> A t)
-  : {t : I | psi t /\ phi t} -> A t
-  := \t -> a t
+    (a : (t : ψ) β†’ A t)
+  : (t : I | ψ t ∧ Ο† t) β†’ A t
+  := \ t β†’ a t
 ```
 
 Then, how to reformulate an `a` (or `b`) as an extension of its restriction:
@@ -109,14 +109,14 @@ Then, how to reformulate an `a` (or `b`) as an extension of its restriction:
 ```rzk
 -- Reformulate extension type as an extension of a restriction.
 #define ext-of-restrict_psi
-    (a : {t : I | psi t} -> A t)
-  : (t : psi) -> A t [ psi t /\ phi t |-> restrict_psi a t ]
+    (a : (t : ψ) β†’ A t)
+  : (t : ψ) β†’ A t [ ψ t ∧ Ο† t ↦ restrict_psi a t ]
   := a  -- type is coerced automatically here
 
 -- Reformulate extension type as an extension of a restriction.
 #define ext-of-restrict_phi
-    (a : {t : I | phi t} -> A t)
-  : (t : phi) -> A t [ psi t /\ phi t |-> restrict_phi a t ]
+    (a : (t : Ο†) β†’ A t)
+  : (t : Ο†) β†’ A t [ ψ t ∧ Ο† t ↦ restrict_phi a t ]
   := a  -- type is coerced automatically here
 ```
 
@@ -125,40 +125,40 @@ Now, assuming relative function extensionality, we construct a path between rest
 ```rzk
 -- Transform extension of an identity into an identity of restrictions.
 #define restricts-path
-    (a_psi : (t : psi) -> A t)
-    (a_phi : (t : phi) -> A t)
-    (e : {t : I | psi t /\ phi t} -> a_psi t = a_phi t)
+    (a_psi : (t : ψ) β†’ A t)
+    (a_phi : (t : Ο†) β†’ A t)
+    (e : (t : I | ψ t ∧ Ο† t) β†’ a_psi t = a_phi t)
   : restrict_psi a_psi = restrict_phi a_phi
   := (first (second (r I
-      (\t -> psi t /\ phi t)
-      (\t -> BOT)
-      (\t -> A t)
-      (\t -> recBOT)
-      (\t -> a_psi t)
-      (\t -> a_phi t)))) e
+      (\t β†’ ψ t ∧ Ο† t)
+      (\t β†’ BOT)
+      (\t β†’ A t)
+      (\t β†’ recBOT)
+      (\t β†’ a_psi t)
+      (\t β†’ a_phi t)))) e
 ```
 
 Finally, we bring everything together into `recId`:
 
 ```rzk
 -- A weaker version of recOR, demanding only a path between a and b:
--- recOR(psi, phi, a, b) demands that for psi /\ phi we have a == b (definitionally)
--- (recId psi phi a b e) demands that e is the proof that a = b (intensionally) for psi /\ phi
+-- recOR(ψ, Ο†, a, b) demands that for ψ ∧ Ο† we have a == b (definitionally)
+-- (recId ψ Ο† a b e) demands that e is the proof that a = b (intensionally) for ψ ∧ Ο†
 #define recId uses (r) -- we declare that recId is using r on purpose
-    (a_psi : (t : psi) -> A t)
-    (a_phi : (t : phi) -> A t)
-    (e : {t : I | psi t /\ phi t} -> a_psi t = a_phi t)
-  : {t : I | psi t \/ phi t} -> A t
-  := \t -> recOR(
-        psi t |-> transport
-          ({s : I | psi s /\ phi s} -> A s)
-          (\ra -> (s : psi) -> A s [ psi s /\ phi s |-> ra s ])
+    (a_psi : (t : ψ) β†’ A t)
+    (a_phi : (t : Ο†) β†’ A t)
+    (e : (t : I | ψ t ∧ Ο† t) β†’ a_psi t = a_phi t)
+  : (t : I | ψ t ∨ Ο† t) β†’ A t
+  := \t β†’ recOR(
+        ψ t ↦ transport
+          ((s : I | ψ s ∧ Ο† s) β†’ A s)
+          (\ra β†’ (s : ψ) β†’ A s [ ψ s ∧ Ο† s ↦ ra s ])
           (restrict_psi a_psi)
           (restrict_phi a_phi)
           (restricts-path a_psi a_phi e)
           (ext-of-restrict_psi a_psi)
           t,
-        phi t |-> ext-of-restrict_phi a_phi t
+        Ο† t ↦ ext-of-restrict_phi a_phi t
       )
 
 #end construction-of-recId
@@ -175,16 +175,16 @@ whenever we can show that they are equal on the intersection of shapes:
 #define id-along-border
     (r : relfunext2)
     (I : CUBE)
-    (psi : I -> TOPE)
-    (phi : I -> TOPE)
-    (A : {t : I | psi t \/ phi t} -> U)
-    (a b : {t : I | psi t \/ phi t} -> A t)
-    (e_psi : (t : psi) -> a t = b t)
-    (e_phi : (t : phi) -> a t = b t)
-    (border-is-a-set : {t : I | psi t /\ phi t} -> isaset (A t))
-  : {t : I | psi t \/ phi t} -> a t = b t
-  := recId r I psi phi
-        (\t -> a t = b t)
+    (ψ : I β†’ TOPE)
+    (Ο† : I β†’ TOPE)
+    (A : (t : I | ψ t ∨ Ο† t) β†’ U)
+    (a b : (t : I | ψ t ∨ Ο† t) β†’ A t)
+    (e_psi : (t : ψ) β†’ a t = b t)
+    (e_phi : (t : Ο†) β†’ a t = b t)
+    (border-is-a-set : (t : I | ψ t ∧ Ο† t) β†’ isaset (A t))
+  : (t : I | ψ t ∨ Ο† t) β†’ a t = b t
+  := recId r I ψ Ο†
+        (\t β†’ a t = b t)
         e_psi e_phi
-        (\t -> border-is-a-set t (a t) (b t) (e_psi t) (e_phi t))
+        (\t β†’ border-is-a-set t (a t) (b t) (e_psi t) (e_phi t))
 ```
diff --git a/docs/docs/getting-started/changelog.md b/docs/docs/getting-started/changelog.md
index eebeeb85f..4bbfc6fe2 100644
--- a/docs/docs/getting-started/changelog.md
+++ b/docs/docs/getting-started/changelog.md
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to the
 [Haskell Package Versioning Policy](https://pvp.haskell.org/).
 
+## v0.6.5 β€” 2023-10-01
+
+This version contains mostly intrastructure improvements:
+
+- Typecheck using `rzk.yaml` if it exists (see [#119](https://github.com/rzk-lang/rzk/pull/119))
+- Update Rzk Playground and Nix Flake (see [#84](https://github.com/rzk-lang/rzk/pull/84))
+  - Rzk Playground now uses CodeMirror 6 and NextJS
+  - `miso` dependency is dropped
+  - GHCJS 9.6 is now used
+  - Support `snippet={code}` or `code={code}` param (see [#118](https://github.com/rzk-lang/rzk/pull/118))
+    - Support for `snippet_url={URL}` is temporarily dropped
+- Update to GHC 9.6, latest Stackage Nightly, improve Rzk setup, and GitHub Actions (see [#116](https://github.com/rzk-lang/rzk/pull/116))
+- Add logging for Rzk Language Server (see [#114](https://github.com/rzk-lang/rzk/pull/114))
+
+Fixes:
+
+- Fix error messages in Rzk Playground (see [#115](https://github.com/rzk-lang/rzk/pull/115))
+
 ## v0.6.4 β€” 2023-09-27
 
 This version improves the stucture of the project, in particular w.r.t dependencies:
diff --git a/docs/docs/index.md b/docs/docs/index.md
index 209eae43e..17f0a8ed6 100644
--- a/docs/docs/index.md
+++ b/docs/docs/index.md
@@ -1,3 +1,17 @@
 # rzk β€” an experimental proof assistant for synthetic ∞-categories
 
 `rzk` is an early prototype of a proof assistant for a family of type systems, including Riehl and Shulman's «Type Theory for Synthetic ∞-categories» ([https://arxiv.org/abs/1705.07442](https://arxiv.org/abs/1705.07442)).
+
+[Get started with Rzk](getting-started/install.md){ .md-button .md-button--primary }
+[Try Rzk Playground](playground/){ .md-button }
+
+## About this project
+
+This project has started with the idea of bringing Riehl and Shulman's 2017 paper [1] to "life" by implementing a proof assistant based on their type theory with shapes. Currently an early prototype with an [online playground](https://rzk-lang.github.io/rzk/develop/playground/) is available. The current implementation is capable of checking various formalisations. Perhaps, the largest formalisations are available in two related projects: <https://rzk-lang.github.com/sHoTT> and <https://github.com/emilyriehl/yoneda>. `sHoTT` project (originally a fork of the yoneda project) aims to cover more formalisations in simplicial HoTT and ∞-categories, while `yoneda` project aims to compare different formalisations of the Yoneda lemma.
+
+Internally, `rzk` uses a version of second-order abstract syntax allowing relatively straightforward handling of binders (such as lambda abstraction). In the future, `rzk` aims to support dependent type inference relying on E-unification for second-order abstract syntax [2].
+Using such representation is motivated by automatic handling of binders and easily automated boilerplate code. The idea is that this should keep the implementation of `rzk` relatively small and less error-prone than some of the existing approaches to implementation of dependent type checkers.
+
+An important part of `rzk` is a tope layer solver, which is essentially a theorem prover for a part of the type theory. A related project, dedicated just to that part is available at <https://github.com/fizruk/simple-topes>. `simple-topes` supports used-defined cubes, topes, and tope layer axioms. Once stable, `simple-topes` will be merged into `rzk`, expanding the proof assistant to the type theory with shapes, allowing formalisations for (variants of) cubical, globular, and other geometric versions of HoTT.
+
+See the list of contributors at [docs/docs/CONTRIBUTORS.md](docs/docs/CONTRIBUTORS.md).
diff --git a/docs/docs/related/sHoTT.md b/docs/docs/related/sHoTT.md
index 029732444..4e2833e13 100644
--- a/docs/docs/related/sHoTT.md
+++ b/docs/docs/related/sHoTT.md
@@ -1,6 +1,6 @@
 # sHoTT
 
-<a href="https://github.com/fizruk/sHoTT" target="_blank">sHoTT</a> is a formalisation project for simplicial HoTT and ∞-categories.
+<a href="https://github.com/rzk-lang/sHoTT" target="_blank">sHoTT</a> is a formalisation project for simplicial HoTT and ∞-categories.
 
 The project is a fork of <a href="https://github.com/emilyriehl/yoneda" target="_blank">https://github.com/emilyriehl/yoneda</a>,
 with a goal to grow and eventually include various
@@ -8,4 +8,4 @@ formalisations for HoTT (e.g. HoTT book),
 synthetic fibered ∞-categories from the work of Ulrik Buchholtz and Jonathan Weinberger, variations of cubical type theories, etc.
 
 See more details in the documentation of the project at
-<a href="https://github.com/fizruk/sHoTT" target="_blank">https://github.com/fizruk/sHoTT</a>.
+<a href="https://github.com/rzk-lang/sHoTT" target="_blank">https://github.com/rzk-lang/sHoTT</a>.
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index c45d21394..815cb6c59 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -6,6 +6,7 @@ edit_uri: edit/develop/docs/docs/
 nav:
   - General:
     - About: index.md
+    - Contributors: CONTRIBUTORS.md
   - Getting Started:
     - Install: getting-started/install.md
     - Quickstart: getting-started/quickstart.rzk.md
diff --git a/flake.lock b/flake.lock
index 2170d390e..8f9e48b36 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,15 +1,31 @@
 {
   "nodes": {
+    "flake-compat": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1673956053,
+        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
     "flake-utils": {
       "inputs": {
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1681202837,
-        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
+        "lastModified": 1694529238,
+        "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
+        "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
         "type": "github"
       },
       "original": {
@@ -18,43 +34,77 @@
         "type": "github"
       }
     },
+    "jsaddle": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1694167118,
+        "narHash": "sha256-QNWimHH7c0xYe8sVmS2U3CgCR2q2fz2G35XTUywSrk8=",
+        "owner": "ghcjs",
+        "repo": "jsaddle",
+        "rev": "ffcda85943fd4b91a715643b921a10df9aba44e1",
+        "type": "github"
+      },
+      "original": {
+        "owner": "ghcjs",
+        "repo": "jsaddle",
+        "type": "github"
+      }
+    },
     "miso": {
       "flake": false,
       "locked": {
-        "lastModified": 1675453995,
-        "narHash": "sha256-rvNgA1ptB8UTBZMn1pjk6nN0CSNekF7oKc00SlpHX4I=",
+        "lastModified": 1691794309,
+        "narHash": "sha256-TQ6SRXDOit24jWnlNAh10FF5NQu8V6tbrY7ry56Cu7w=",
         "owner": "dmjio",
         "repo": "miso",
-        "rev": "5c66ed20818ce4aff81aaefbd5789007717923eb",
+        "rev": "49edf0677253bbcdd473422b5dd5b4beffd83910",
         "type": "github"
       },
       "original": {
         "owner": "dmjio",
         "repo": "miso",
-        "rev": "5c66ed20818ce4aff81aaefbd5789007717923eb",
+        "rev": "49edf0677253bbcdd473422b5dd5b4beffd83910",
+        "type": "github"
+      }
+    },
+    "nix-filter": {
+      "locked": {
+        "lastModified": 1694857738,
+        "narHash": "sha256-bxxNyLHjhu0N8T3REINXQ2ZkJco0ABFPn6PIe2QUfqo=",
+        "owner": "numtide",
+        "repo": "nix-filter",
+        "rev": "41fd48e00c22b4ced525af521ead8792402de0ea",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "nix-filter",
         "type": "github"
       }
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1684242266,
-        "narHash": "sha256-uaCQ2k1bmojHKjWQngvnnnxQJMY8zi1zq527HdWgQf8=",
+        "lastModified": 1694934517,
+        "narHash": "sha256-U9aI4/jw+kYTZye4LJC2eIU30SqvZgL/UeRY4VHIjK8=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "7e0743a5aea1dc755d4b761daf75b20aa486fdad",
+        "rev": "e1b4c97ed4ce160afd9ef1574b6a2ff168482f2a",
         "type": "github"
       },
       "original": {
         "owner": "NixOS",
-        "ref": "nixpkgs-unstable",
         "repo": "nixpkgs",
+        "rev": "e1b4c97ed4ce160afd9ef1574b6a2ff168482f2a",
         "type": "github"
       }
     },
     "root": {
       "inputs": {
+        "flake-compat": "flake-compat",
         "flake-utils": "flake-utils",
+        "jsaddle": "jsaddle",
         "miso": "miso",
+        "nix-filter": "nix-filter",
         "nixpkgs": "nixpkgs"
       }
     },
diff --git a/flake.nix b/flake.nix
index 89ae38c2e..595a589e8 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,9 +1,18 @@
 {
   inputs = {
     flake-utils.url = "github:numtide/flake-utils";
-    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+    nixpkgs.url = "github:NixOS/nixpkgs/e1b4c97ed4ce160afd9ef1574b6a2ff168482f2a";
     miso = {
-      url = "github:dmjio/miso/5c66ed20818ce4aff81aaefbd5789007717923eb";
+      url = "github:dmjio/miso/49edf0677253bbcdd473422b5dd5b4beffd83910";
+      flake = false;
+    };
+    flake-compat = {
+      url = "github:edolstra/flake-compat";
+      flake = false;
+    };
+    nix-filter.url = "github:numtide/nix-filter";
+    jsaddle = {
+      url = "github:ghcjs/jsaddle";
       flake = false;
     };
   };
@@ -12,84 +21,45 @@
       pkgs = inputs.nixpkgs.legacyPackages.${system};
 
       rzk = "rzk";
-      try-rzk = "try-rzk";
-      ghcVersion = "ghc927";
-
-      # select a Haskell package set for a specified GHC version
-      hpkgs = pkgs.haskell.packages.${ghcVersion};
-
-      inherit (pkgs.haskell.lib) overrideCabal;
-
-      # Provide overrides
-      # https://nixos.wiki/wiki/Haskell#Overrides
-      # An override should include a local package into the Haskell package set
-      override = {
-        overrides = self: super: {
-          ${rzk} = overrideCabal (self.callCabal2nix rzk ./${rzk} { }) (x: {
-            librarySystemDepends = [ pkgs.alex pkgs.happy ] ++ (x.librarySystemDepends or [ ]);
-          });
-          ${try-rzk} = overrideCabal (self.callCabal2nix try-rzk ./${try-rzk} { }) (x: {
-            executableSystemDepends = [ self.ghcjs-prim self.ghcjs-base ] ++ (x.executableSystemDepends or [ ]);
-          });
-        };
-      };
-      hpkgs_ = hpkgs.override override;
-
-      # Get all dependencies of local Haskell packages excluding these local packages
-      # This approach is useful for cases when a local package A depends on a local package B
-      # In this case, package B won't be built by Nix as a dependency of A
-      getHaskellPackagesDeps = someHaskellPackages: let l = pkgs.lib.lists; in (l.subtractLists someHaskellPackages (l.concatLists (map (package: l.concatLists (__attrValues package.getCabalDeps)) someHaskellPackages)));
-
-      # build a GHC with the dependencies of local Haskell packages
-      ghcForPackages = localHaskellPackageNames: hpkgs_.ghcWithPackages (ps: (getHaskellPackagesDeps (map (x: ps.${x}) localHaskellPackageNames) ++ [ ps.haskell-language-server ])); # Why provide HLS here - https://github.com/NixOS/nixpkgs/issues/225895#issuecomment-1509991742
+      rzk-js = "rzk-js";
+      ghcVersion = "ghc962";
+      rzk-src = (inputs.nix-filter {
+        root = ./${rzk};
+        include = [ "app" "src" "test" "package.yaml" ];
+      });
+      rzk-js-src = (inputs.nix-filter {
+        root = ./${rzk-js};
+        include = [ "Main.hs" "${rzk-js}.cabal" ];
+      });
 
-      # GHC with dependencies of local Haskell packages
-      ghc = ghcForPackages [ rzk try-rzk ];
-
-      # tools that should be available in a development shell
       tools = [
         pkgs.cabal-install
         pkgs.hpack
-        # haskell-language-server is already available as a GHC package
-        ghc
+        pkgs.nodejs_18
+        pkgs.bun
       ];
 
-      misoNix = (import "${inputs.miso.outPath}/default.nix" { inherit system; });
-      pkgsMiso = misoNix.pkgs;
-
-      # TODO add jsaddle version of the app
-      # https://github.com/dmjio/miso/tree/master/sample-app-jsaddle
-      # try-rzk-dev =
-      #   let
-      #     pkgsDev = pkgsMiso.haskell.packages.ghc865;
-      #     rzk = pkgsDev.callPackage rzk/rzk.nix { inherit (pkgs) hpack; };
-      #   in
-      #   pkgsDev.callCabal2nix try-rzk ./${try-rzk} { miso = misoNix.miso-jsaddle; rzk = rzk; };
+      default = import ./nix/default.nix { inherit inputs pkgs rzk rzk-src ghcVersion tools; };
+      ghcjs = import ./nix/ghcjs.nix { inherit inputs pkgs scripts rzk rzk-src rzk-js rzk-js-src ghcVersion tools; };
+      scripts = import ./nix/scripts.nix { inherit pkgs packages; };
 
-      try-rzk-exe =
-        let
-          pkgsRelease = pkgsMiso.haskell.packages.ghcjs;
-          rzk = pkgsRelease.callPackage rzk/rzk.nix { inherit (pkgs) hpack; };
-        in
-        pkgsRelease.callCabal2nix try-rzk ./${try-rzk} { rzk = rzk; };
 
       packages = {
-        rzk = hpkgs_.${rzk};
-        try-rzk = try-rzk-exe;
-      };
+        default = default.packages.default;
+        rzk = default.packages.${rzk};
+        rzk-js = ghcjs.packages.${rzk-js};
+      } // scripts;
 
       devShells = {
-        default = pkgs.mkShell {
-          shellHook = "export LANG=C.utf8";
-          buildInputs = tools;
+        default = default.devShells.default;
+        ghcjs = ghcjs.devShells.default;
+        release = pkgs.mkShell {
+          buildInputs = [ scripts.release-rzk-playground ];
         };
-        ghcjs = try-rzk-exe.env.overrideAttrs (old: {
-          buildInputs = old.buildInputs ++ [ pkgs.cabal-install pkgs.hpack ];
-        });
       };
     in
     {
-      inherit packages devShells;
+      inherit packages devShells default ghcjs;
     });
 
   nixConfig = {
diff --git a/hie.yaml b/hie.yaml
new file mode 100644
index 000000000..f0c7014d7
--- /dev/null
+++ b/hie.yaml
@@ -0,0 +1,2 @@
+cradle:
+  cabal:
\ No newline at end of file
diff --git a/nix/default.nix b/nix/default.nix
new file mode 100644
index 000000000..3d0ef9001
--- /dev/null
+++ b/nix/default.nix
@@ -0,0 +1,27 @@
+{ inputs, pkgs, ghcVersion, rzk, rzk-src, tools }:
+let
+  inherit (pkgs.haskell.lib) overrideCabal;
+  # https://nixos.wiki/wiki/Haskell#Overrides
+  hpkgs = pkgs.haskell.packages.${ghcVersion}.override {
+    overrides = final: prev: {
+      ${rzk} = final.callCabal2nix rzk rzk-src { };
+    };
+  };
+
+  devShells = {
+    default =
+      hpkgs.shellFor {
+        shellHook = "export LANG=C.utf8";
+        packages = ps: [ ps.rzk ];
+        nativeBuildInputs = tools ++ [ hpkgs.haskell-language-server ];
+      };
+  };
+
+  packages = {
+    default = pkgs.haskell.lib.justStaticExecutables hpkgs.${rzk};
+    rzk = hpkgs.${rzk};
+  };
+in
+{
+  inherit hpkgs devShells packages;
+}
diff --git a/nix/ghcjs.nix b/nix/ghcjs.nix
new file mode 100644
index 000000000..f243e9511
--- /dev/null
+++ b/nix/ghcjs.nix
@@ -0,0 +1,77 @@
+{ inputs, pkgs, scripts, rzk, rzk-js, rzk-src, rzk-js-src, ghcVersion, tools }:
+let
+  inherit (pkgs.haskell.lib) overrideCabal;
+  misoNix = (import "${inputs.miso.outPath}/default.nix" { inherit (pkgs) system; });
+  pkgsMiso = misoNix.pkgs;
+
+  hpkgs =
+    # This isn't equivalent to `pkgsMiso.haskell.packages.ghcjs.override` ([link](https://nixos.wiki/wiki/Haskell#Overrides))
+    # but avoids multiple rebuilds
+    pkgsMiso.haskell.packages.ghcjs //
+    {
+      rzk = overrideCabal
+        (hpkgs.callCabal2nix rzk rzk-src { })
+        (x: {
+          isLibrary = true;
+          isExecutable = false;
+          doCheck = false;
+          doHaddock = false;
+          libraryToolDepends = [ pkgs.hpack pkgs.alex pkgs.happy ] ++ (x.libraryToolDepends or [ ]);
+          testToolDepends = [ pkgs.hpack pkgs.alex pkgs.happy ] ++ (x.testToolDepends or [ ]);
+          prePatch = "hpack --force";
+        });
+      rzk-js = overrideCabal
+        (hpkgs.callCabal2nix rzk-js rzk-js-src { inherit (hpkgs) rzk; })
+        (x: {
+          postInstall = (x.postInstall or "") + ''
+            cp $out/bin/${rzk-js} .
+            rm -r $out
+            cp ${rzk-js} $out
+          '';
+        });
+    };
+
+  hpkgsGHCJS_8_10_7 = pkgs.haskell.packages.ghcjs810.override ({
+    overrides = final: prev: {
+      integer-gmp = final.integer-gmp_1_1;
+      rzk = overrideCabal
+        (final.callCabal2nix rzk rzk-src { })
+        (x: {
+          isLibrary = true;
+          isExecutable = false;
+          doCheck = false;
+          doHaddock = false;
+          libraryToolDepends = [ pkgs.hpack pkgs.alex pkgs.happy ] ++ (x.libraryToolDepends or [ ]);
+          testToolDepends = [ pkgs.hpack pkgs.alex pkgs.happy ] ++ (x.testToolDepends or [ ]);
+          prePatch = "hpack --force";
+        });
+      rzk-js = overrideCabal
+        (final.callCabal2nix rzk-js rzk-js-src { inherit (final) rzk; })
+        (x: {
+          postInstall = (x.postInstall or "") + ''
+            rm -r $out/bin/${rzk-js}.jsexe
+          '';
+        });
+    };
+  });
+
+  packages = {
+    inherit (hpkgs) rzk rzk-js;
+
+    # Currently not buildable
+    rzk_8_10_7 = hpkgsGHCJS_8_10_7.rzk;
+    rzk-js_8_10_7 = hpkgsGHCJS_8_10_7;
+  };
+
+  devShells = {
+    default = (hpkgs.shellFor {
+      packages = _: [ hpkgs.${rzk} hpkgs.${rzk-js} ];
+      nativeBuildInputs = tools ++ [ scripts.build-rzk-js ];
+    }).overrideAttrs (x: {
+      buildInputs = builtins.filter (p: (p.name or "") != "ghc-8.6.4") (x.buildInputs or [ ]);
+    });
+  };
+in
+{
+  inherit hpkgs devShells packages hpkgsGHCJS_8_10_7;
+}
diff --git a/nix/js-backend.nix b/nix/js-backend.nix
new file mode 100644
index 000000000..976d3d128
--- /dev/null
+++ b/nix/js-backend.nix
@@ -0,0 +1,79 @@
+# TODO fix builds with JS backend
+
+{ inputs, pkgs, rzk, rzk-js, rzk-src, rzk-js-src, ghcVersion, tools }:
+let
+  inherit (pkgs.haskell.lib) overrideCabal;
+  overrideJS = {
+    overrides = self: super: {
+      jsaddle = super.callCabal2nix "jsaddle" "${inputs.jsaddle.outPath}/jsaddle" { };
+      rzk = overrideCabal
+        (super.callCabal2nix rzk rzk-src { })
+        (x: {
+          isLibrary = true;
+          isExecutable = false;
+          doCheck = false;
+          doHaddock = false;
+          libraryToolDepends = [ pkgs.hpack pkgs.alex pkgs.happy ] ++ (x.libraryToolDepends or [ ]);
+          testToolDepends = [ pkgs.hpack pkgs.alex pkgs.happy ] ++ (x.testToolDepends or [ ]);
+          prePatch = "hpack --force";
+        });
+      rzk-js = overrideCabal
+        (super.callCabal2nix rzk-js rzk-js-src { inherit (self) rzk; })
+        (x: {
+          postInstall = (x.postInstall or "") + ''
+            rm -r $out/bin/${rzk-js}.jsexe
+          '';
+        });
+    };
+  };
+  hpkgs = pkgs.pkgsCross.ghcjs.buildPackages.haskell.packages.${ghcVersion}.override overrideJS;
+
+  # Get all dependencies of local Haskell packages excluding these local packages
+  # This approach is useful for cases when a local package A depends on a local package B
+  # In this case, package B won't be built by Nix as a dependency of A
+  getHaskellPackagesDeps = someHaskellPackages: let l = pkgs.lib.lists; in (l.subtractLists someHaskellPackages (l.concatLists (map (package: l.concatLists (__attrValues package.getCabalDeps)) someHaskellPackages)));
+  # build a GHC with the dependencies of local Haskell packages
+  ghcForPackages = hpkgs_: localHaskellPackageNames: hpkgs_.ghcWithPackages (ps: (getHaskellPackagesDeps (map (x: ps.${x}) localHaskellPackageNames) ++ [ ps.haskell-language-server ])); # Why provide HLS here - https://github.com/NixOS/nixpkgs/issues/225895#issuecomment-1509991742
+
+  ghcWithPackages = ghcForPackages hpkgs [ rzk rzk-js ];
+
+  ghc = pkgs.pkgsCross.ghcjs.buildPackages.haskell.compiler.${ghcVersion};
+
+  packages = {
+    # TODO fix doesn't build .js
+    inherit (hpkgs) rzk rzk-js;
+  };
+
+  devShells = {
+    # This devshell provides a GHC compiler with packages that are dependencies of `rzk` and `rzk-js`
+    # It should be a GHC with a JS backend, but it's an ordinary GHC for some reason
+
+    default = hpkgs.shellFor {
+      packages = ps: [ ps.rzk ps.${rzk-js} ];
+      nativeBuildInputs = tools;
+    };
+
+    # This devshell provides a GHC compiler with packages that are dependencies of `rzk` and `rzk-js`
+    # It should be a GHC with a JS backend, but it's an ordinary GHC for some reason
+
+    ghcWithPackages = pkgs.mkShell {
+      buildInputs = [ ghcWithPackages ] ++ tools;
+    };
+
+    # This devshell provides a GHC compiler with JS backend and without extra packages
+
+    # GHC fails to build `rzk-js`
+    # cabal --with-compiler=javascript-unknown-ghcjs-ghc --with-ghc-pkg=javascript-unknown-ghcjs-ghc-pkg build rzk-js
+    ghcJS = pkgs.mkShell {
+      buildInputs = [ ghc ] ++ tools;
+    };
+
+
+    # TODO incremental builds for ghc with js backend
+    # Incremental builds work for ghc 9.6+
+    # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/haskell.section.md#incremental-builds-haskell-incremental-builds
+  };
+in
+{
+  inherit hpkgs devShells packages ghc ghcForPackages;
+}
diff --git a/nix/scripts.nix b/nix/scripts.nix
new file mode 100644
index 000000000..8687cd2a4
--- /dev/null
+++ b/nix/scripts.nix
@@ -0,0 +1,95 @@
+{ pkgs, packages }:
+let scripts =
+  {
+    build-rzk-js = pkgs.writeShellApplication {
+      name = "build-rzk-js";
+      text =
+        let
+          public = "rzk-playground/public";
+          result = "${public}/rzk-js";
+        in
+        ''
+          cabal install rzk-js --ghcjs --installdir ${result}
+          rm -f ${public}/rzk.js
+          
+          cp ${result}/rzk-js ${public}/rzk.js
+          printf "Copied ${result}/rzk-js to ${public}/rzk.js\n"
+          
+          rm -rf ${result}
+          printf "Removed ${result}\n"
+        '';
+    };
+
+    save-flake = pkgs.writeShellApplication {
+      name = "save-flake";
+      runtimeInputs = [ pkgs.jq ];
+      text = ''
+        # save flake inputs - # https://github.com/NixOS/nix/issues/4250#issuecomment-1146878407
+
+        mkdir -p "/nix/var/nix/gcroots/per-user/$USER"
+        
+        gc_root_prefix="/nix/var/nix/gcroots/per-user/$USER/$(systemd-escape -p "$PWD")-flake-"
+        echo "Adding per-user gcroots..."
+        rm -f "$gc_root_prefix"*
+        nix flake archive --json 2>/dev/null \
+          | jq -r '.inputs | to_entries[] | "ln -fsT "+.value.path+" \"'"$gc_root_prefix"'"+.key+"\""' \
+          | while read -r line; \
+            do
+              eval "$line"
+            done
+      
+        # save scripts
+
+        nix profile install --profile "$gc_root_prefix""${scripts.save-flake.name}" .#${scripts.save-flake.name}
+        nix profile install --profile "$gc_root_prefix""${scripts.release-rzk-playground.name}" .#${scripts.release-rzk-playground.name}
+
+        printf "Entries saved with prefix %s\n" "$gc_root_prefix"
+      '';
+    };
+
+    release-rzk-playground = pkgs.writeShellApplication {
+      name = "release-rzk-playground";
+      runtimeInputs = [ pkgs.nodejs_18 packages.build-rzk-js ];
+      text =
+        let
+          playground = "rzk-playground";
+          playground-rzk-js = "${playground}/public/rzk.js";
+          config = "next.config.js";
+          configTmp = "${config}.tmp";
+          configBackup = "${config}.bk";
+          release = "rzk-playground-release";
+        in
+        ''
+          rm -f ${playground-rzk-js}
+          mkdir -p "$(dirname ${playground-rzk-js})"
+          cp ${packages.rzk-js} ${playground-rzk-js}
+              
+          (
+            cd ${playground}
+            npm i
+                
+            # empty string by default
+                
+            : "''${BASEPATH:=""}"
+
+            # substitute basepath in config
+
+            < ${config} sed "s|'''|'$BASEPATH'|" > ${configTmp}
+            mv ${config} ${configBackup}
+            mv ${configTmp} ${config}
+
+            # restore backup anyway
+                
+            npm run build || true
+            mv ${configBackup} ${config}
+          )
+
+          rm -rf ${release}
+          mkdir ${release}
+          cp -r ${playground}/out/* ${release}
+
+          printf "Wrote release files to '${release}'\n"
+        '';
+    };
+  };
+in scripts
diff --git a/rzk-js/Main.hs b/rzk-js/Main.hs
new file mode 100644
index 000000000..ea1812162
--- /dev/null
+++ b/rzk-js/Main.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main where
+
+import qualified GHCJS.Foreign.Callback as GHCJS
+import GHCJS.Marshal (fromJSVal, toJSVal)
+import GHCJS.Prim (JSVal)
+import Data.JSString(JSString, pack)
+import JavaScript.Object
+import JavaScript.Object.Internal (Object (..), create)
+import qualified Rzk.Main as Rzk
+import System.IO
+
+main :: IO ()
+main = do
+  putStr "Haskell logic core starting"
+  hFlush stdout
+
+  -- https://discourse.haskell.org/t/compile-library-with-ghcjs/4727
+  callback <- GHCJS.syncCallback1 GHCJS.ThrowWouldBlock $ \jsval -> do
+    let o = Object jsval
+    rawInput <- getProp "input" o
+    input <- maybe (Left "Could not turn JSRef to a String") Right <$> fromJSVal rawInput
+
+    case Rzk.typecheckString =<< input of
+      Left err -> setStringProp "status" "error" o >> setStringProp "result" (pack err) o
+      Right ok -> setStringProp "status" "ok" o >> setStringProp "result" (pack ok) o
+
+  set_rzk_typecheck_callback callback
+
+  putStr "Haskell logic core callbacks initialized"
+
+setStringProp :: JSString -> JSString -> Object -> IO ()
+setStringProp name valueRaw object = do
+  value <- toJSVal valueRaw
+  setProp name value object
+
+foreign import javascript unsafe "rzkTypecheck_ = $1"
+  set_rzk_typecheck_callback :: GHCJS.Callback (JSVal -> IO ()) -> IO ()
diff --git a/try-rzk/try-rzk.cabal b/rzk-js/rzk-js.cabal
similarity index 79%
rename from try-rzk/try-rzk.cabal
rename to rzk-js/rzk-js.cabal
index 10c792403..4465e8d86 100644
--- a/try-rzk/try-rzk.cabal
+++ b/rzk-js/rzk-js.cabal
@@ -1,15 +1,15 @@
-name:                try-rzk
+name:                rzk-js
 version:             0.1.0
 synopsis:            A serverless online version of Rzk proof assistant
 category:            Web
 build-type:          Simple
 cabal-version:       >=1.10
 
-executable try-rzk
+executable rzk-js
   main-is:             Main.hs
   ghcjs-options:
     -dedupe
-  build-depends:       base, miso, rzk
+  build-depends:       base, rzk
   if impl(ghcjs)
     build-depends:
       ghcjs-base, ghcjs-prim
diff --git a/rzk-playground/.eslintrc.json b/rzk-playground/.eslintrc.json
new file mode 100644
index 000000000..73601b742
--- /dev/null
+++ b/rzk-playground/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+  "extends": [
+    "next"
+  ]
+}
\ No newline at end of file
diff --git a/rzk-playground/.gitignore b/rzk-playground/.gitignore
new file mode 100644
index 000000000..6a01e9822
--- /dev/null
+++ b/rzk-playground/.gitignore
@@ -0,0 +1,37 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
+public/rzk.js
\ No newline at end of file
diff --git a/rzk-playground/README.md b/rzk-playground/README.md
new file mode 100644
index 000000000..c4033664f
--- /dev/null
+++ b/rzk-playground/README.md
@@ -0,0 +1,36 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+# or
+bun dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/rzk-playground/app/globals.css b/rzk-playground/app/globals.css
new file mode 100644
index 000000000..681e443e2
--- /dev/null
+++ b/rzk-playground/app/globals.css
@@ -0,0 +1,91 @@
+section {
+  width: 100%;
+}
+
+body {
+  margin: 0;
+  background-color: #000;
+}
+
+.row {
+  display: flex;
+  justify-content: space-evenly;
+  margin: 0;
+  padding: 0;
+  width: 100%;
+}
+
+.column {
+  margin-top: 0;
+  margin-bottom: 0;
+  width: 100%;
+}
+
+/* CSS for response button from https://getcssscan.com/css-buttons-examples (button 61) */
+#btnTypecheck {
+  align-items: center;
+  appearance: none;
+  border-radius: 4px;
+  border-style: none;
+  box-shadow: rgba(0, 0, 0, .2) 0 3px 1px -2px, rgba(0, 0, 0, .14) 0 2px 2px 0, rgba(0, 0, 0, .12) 0 1px 5px 0;
+  box-sizing: border-box;
+  color: #fff;
+  cursor: pointer;
+  display: inline-flex;
+  font-family: Roboto, sans-serif;
+  font-size: .875rem;
+  font-weight: 500;
+  height: 36px;
+  justify-content: center;
+  letter-spacing: .0892857em;
+  line-height: normal;
+  min-width: 64px;
+  outline: none;
+  overflow: visible;
+  padding: 0 16px;
+  position: relative;
+  text-align: center;
+  text-decoration: none;
+  text-transform: uppercase;
+  transition: box-shadow 280ms cubic-bezier(.4, 0, .2, 1);
+  user-select: none;
+  -webkit-user-select: none;
+  touch-action: manipulation;
+  vertical-align: middle;
+  will-change: transform, opacity;
+}
+
+#btnTypecheck:hover {
+  box-shadow: rgba(0, 0, 0, .2) 0 2px 4px -1px, rgba(0, 0, 0, .14) 0 4px 5px 0, rgba(0, 0, 0, .12) 0 1px 10px 0;
+}
+
+#btnTypecheck:disabled {
+  background-color: rgba(0, 0, 0, .12);
+  box-shadow: rgba(0, 0, 0, .2) 0 0 0 0, rgba(0, 0, 0, .14) 0 0 0 0, rgba(0, 0, 0, .12) 0 0 0 0;
+  color: rgba(0, 0, 0, .37);
+  cursor: default;
+  pointer-events: none;
+}
+
+#btnTypecheck:not(:disabled) {
+  background-color: #6200ee;
+}
+
+#btnTypecheck:focus {
+  box-shadow: rgba(0, 0, 0, .2) 0 2px 4px -1px, rgba(0, 0, 0, .14) 0 4px 5px 0, rgba(0, 0, 0, .12) 0 1px 10px 0;
+}
+
+#btnTypecheck:active {
+  box-shadow: rgba(0, 0, 0, .2) 0 5px 5px -3px, rgba(0, 0, 0, .14) 0 8px 10px 1px, rgba(0, 0, 0, .12) 0 3px 14px 2px;
+  background: #A46BF5;
+}
+
+#message {
+  background-color: #1e1f1c;
+  color: #ffffff;
+  overflow: scroll;
+}
+
+#message pre {
+  font-family: Inconsolata, monospace;
+}
\ No newline at end of file
diff --git a/rzk-playground/app/layout.tsx b/rzk-playground/app/layout.tsx
new file mode 100644
index 000000000..3df54bf87
--- /dev/null
+++ b/rzk-playground/app/layout.tsx
@@ -0,0 +1,21 @@
+import './globals.css'
+import type { Metadata } from 'next'
+import { Inter } from 'next/font/google'
+
+const inter = Inter({ subsets: ['latin'] })
+
+export const metadata: Metadata = {
+  title: 'Try Rzk proof assistant!'
+}
+
+export default function RootLayout({
+  children,
+}: {
+  children: React.ReactNode
+}) {
+  return (
+    <html lang="en">
+      <body className={inter.className}>{children}</body>
+    </html>
+  )
+}
diff --git a/rzk-playground/app/page.tsx b/rzk-playground/app/page.tsx
new file mode 100644
index 000000000..ef07d4f6f
--- /dev/null
+++ b/rzk-playground/app/page.tsx
@@ -0,0 +1,136 @@
+'use client';
+
+import { useCallback, useEffect, useState } from 'react';
+import Editor from '../components/editor/Editor';
+import Script from 'next/script';
+import { Resizable } from 're-resizable';
+import React from 'react';
+import * as rzk from '../src/rzk';
+import { KeyBindProvider, ShortcutType } from 'react-keybinds';
+import dynamic from 'next/dynamic';
+
+var typecheckedOnStart = false
+
+declare var window: Window & typeof globalThis;
+
+function HomeNoSSR() {
+  const [message, setMessage] = useState("Starting...");
+
+  const [windowHeight, setWindowHeight] = useState(window.innerHeight)
+  const [needTypecheck, setNeedTypecheck] = useState(false)
+
+  useEffect(() => {
+    const handleWindowResize = () => {
+      setWindowHeight(window.innerHeight)
+    };
+
+    window.addEventListener('resize', handleWindowResize);
+
+    return () => {
+      window.removeEventListener('resize', handleWindowResize);
+    };
+  }, []);
+
+  const [text, setText] = useState("")
+
+  const typecheck = useCallback(() => {
+    const result = rzk.typecheck(text)
+    if (result.status == 'ok') {
+      setMessage(`Everything is OK!`)
+    } else {
+      setMessage(result.result)
+    }
+  }, [text])
+
+  useEffect(() => {
+    function checkFlag() {
+      if ((!((window as any).rzkTypecheck_) || (text === "")) && !typecheckedOnStart) {
+        console.warn("something bad")
+        console.warn((window as any).rzkTypecheck_)
+        window.setTimeout(checkFlag, 100); /* this checks the flag every 100 milliseconds*/
+      } else if (!typecheckedOnStart) {
+        typecheck()
+        typecheckedOnStart = true
+      }
+    }
+
+    if (!typecheckedOnStart) {
+      checkFlag();
+    }
+  }, [typecheck, text])
+
+  useEffect(() => {
+    if (needTypecheck) {
+      typecheck()
+      setNeedTypecheck(false)
+    }
+  }, [setNeedTypecheck, needTypecheck, typecheck])
+
+  const KEYBINDINGS: ShortcutType[] =
+    [
+      {
+        keys: {
+          Mac: ['Shift', 'Enter'],
+          Windows: ['Shift', 'Enter'],
+          Linux: ['Shift', 'Enter'],
+        },
+        label: 'Test command',
+        callback: () => {
+          setNeedTypecheck(true)
+        },
+      },
+    ]
+    ;
+
+  const [outputHeight, setOutputHeight] = useState(windowHeight * 30 / 100)
+  const [editorHeight, setEditorHeight] = useState(windowHeight * 70 / 100)
+
+  return (
+    <main>
+      <div style={{ height: '100vh', width: '100vw', backgroundColor: '#202028' }}>
+        <Script src='rzk.js' />
+        <KeyBindProvider shortcuts={KEYBINDINGS}></KeyBindProvider>
+        <div style={{ height: '100vh' }}>
+          <Editor
+            setText={setText}
+            setNeedTypecheck={setNeedTypecheck}
+            editorHeight={editorHeight}
+          />
+        </div>
+        <div
+          id={'message'}
+          style={{
+            position: 'fixed',
+            bottom: 0,
+            overflow: 'auto',
+          }}
+        >
+          <Resizable
+            size={{ width: '100vw', height: outputHeight }}
+            minHeight={100}
+            maxHeight={windowHeight - 100}
+            enable={{ top: true }}
+            onResizeStop={(_e, _direction, _ref, d) => {
+              setOutputHeight(outputHeight + d.height)
+            }}
+            onResize={(_e, _direction, _ref, d) => {
+              setEditorHeight(window.innerHeight - (outputHeight + d.height))
+            }}
+            style={{ padding: '20px' }}
+          >
+            <button id='btnTypecheck' onClick={typecheck}>
+              TYPECHECK (SHIFT + ENTER)
+            </button>
+            <pre id='message' style={{ fontSize: 16 }}>{message}</pre>
+          </Resizable>
+        </div>
+      </div>
+    </main>
+  )
+}
+
+const Home = dynamic(() => Promise.resolve(HomeNoSSR), {
+  ssr: false,
+})
+
+export default Home
\ No newline at end of file
diff --git a/rzk-playground/components/editor/Editor.tsx b/rzk-playground/components/editor/Editor.tsx
new file mode 100644
index 000000000..4a797983d
--- /dev/null
+++ b/rzk-playground/components/editor/Editor.tsx
@@ -0,0 +1,72 @@
+'use client';
+
+import CodeMirror from '@uiw/react-codemirror';
+import { EditorView, keymap } from '@codemirror/view'
+import { scrollPastEnd } from '@codemirror/view';
+import { example } from './example';
+import { color, oneDark } from './theme';
+import { Dispatch, SetStateAction, useState } from 'react';
+import { centerCursor } from './cursor-height';
+import { language } from './parser';
+
+export default function Editor({
+    setText,
+    setNeedTypecheck,
+    editorHeight
+}: {
+    setText: Dispatch<SetStateAction<string>>,
+    setNeedTypecheck: React.Dispatch<React.SetStateAction<boolean>>,
+    editorHeight: number
+}) {
+    const [existsSelection, setExistsSelection] = useState(false)
+    const params = new URLSearchParams(window.location.search);
+
+    var snippet = example
+    if (params.has("snippet")) {
+        snippet = params.get("snippet")!;
+    } else if (params.has("code")) {
+        snippet = params.get("code")!;
+    }
+    return <CodeMirror
+        value={snippet}
+        height={`100vh`}
+        width={`100vw`}
+        onCreateEditor={(view) => {
+            setText(snippet)
+            view.dispatch({ effects: EditorView.scrollIntoView(0) })
+        }}
+        onUpdate={(update) => {
+            if (update.selectionSet) {
+                let ranges = update.state.selection.ranges.filter(v => { return v.from != v.to })
+                setExistsSelection(ranges.length > 0)
+            }
+        }}
+        onChange={(value) => {
+            setText(value)
+        }}
+        theme={oneDark}
+        extensions={[
+            keymap.of([
+                {
+                    key: "Shift-Enter", run: () => {
+                        setNeedTypecheck(true)
+                        return true
+                    }
+                }
+            ]),
+            scrollPastEnd(),
+            centerCursor(editorHeight),
+
+            // dynamic parts of the theme
+            EditorView.theme({
+                "& .cm-scroller": {
+                    maxHeight: `${editorHeight}px !important`
+                },
+                "& .cm-activeLine": {
+                    backgroundColor: `${existsSelection ? "transparent" : color.activeLine} !important`
+                },
+            }),
+            language
+        ]}
+    />;
+}
diff --git a/rzk-playground/components/editor/cursor-height.ts b/rzk-playground/components/editor/cursor-height.ts
new file mode 100644
index 000000000..a61641b5d
--- /dev/null
+++ b/rzk-playground/components/editor/cursor-height.ts
@@ -0,0 +1,27 @@
+import { ViewPlugin, ViewUpdate } from "@uiw/react-codemirror"
+
+
+// https://discuss.codemirror.net/t/cm6-scroll-to-middle/2924/4
+export const centerCursor = (editorHeight: number) => ViewPlugin.fromClass(class {
+    update(update: ViewUpdate) {
+        if (update.transactions.some(tr => tr.scrollIntoView)) {
+            let view = update.view
+            // (Sync with other DOM read/write phases for efficiency)
+            view.requestMeasure({
+                read() {
+                    return {
+                        cursor: view.coordsAtPos(view.state.selection.main.head),
+                    }
+                },
+                write({ cursor }) {
+                    if (cursor) {
+                        let cursorHeight = cursor.bottom - cursor.top
+                        let outputTop = editorHeight
+                        if (cursor.bottom + cursorHeight + 5 > outputTop)
+                            view.scrollDOM.scrollTop += ((cursor.bottom + 5) - outputTop)
+                    }
+                }
+            })
+        }
+    }
+})
\ No newline at end of file
diff --git a/rzk-playground/components/editor/example.ts b/rzk-playground/components/editor/example.ts
new file mode 100644
index 000000000..5dc3eed89
--- /dev/null
+++ b/rzk-playground/components/editor/example.ts
@@ -0,0 +1,142 @@
+export const example = `#lang rzk-1
+
+-- A is contractible there exists x : A such that for any y : A we have x = y.
+#def iscontr (A : U) : U
+  := βˆ‘ (a : A), (x : A) -> a =_{A} x
+
+-- A is a proposition if for any x, y : A we have x = y
+#def isaprop (A : U) : U
+  := (x : A) -> (y : A) -> x =_{A} y
+
+-- A is a set if for any x, y : A the type x =_{A} y is a proposition
+#def isaset (A : U) : U
+  := (x : A) -> (y : A) -> isaprop (x =_{A} y)
+
+-- Non-dependent product of A and B
+#def prod (A : U) (B : U) : U
+  := βˆ‘ (x : A), B
+
+-- A function f : A -> B is an equivalence
+-- if there exists g : B -> A
+-- such that for all x : A we have g (f x) = x
+-- and for all y : B we have f (g y) = y
+#def isweq (A : U) (B : U) (f : A -> B) : U
+  := βˆ‘ (g : B -> A), prod ((x : A) -> g (f x) =_{A} x) ((y : B) -> f (g y) =_{B} y)
+
+-- Equivalence of types A and B
+#def weq (A : U) (B : U) : U
+  := βˆ‘ (f : A -> B), isweq A B f
+
+-- Transport along a path
+#def transport
+    (A : U)
+    (C : A -> U)
+    (x y : A)
+    (p : x =_{A} y)
+    : C x -> C y
+  := \\cx -> idJ(A, x, (\\z q -> C z), cx, y, p)
+
+-- [RS17, Axiom 4.6] Relative function extensionality.
+#def relfunext : U
+  := (I : CUBE)
+  -> (psi : I -> TOPE)
+  -> (phi : psi -> TOPE)
+  -> (A : psi -> U)
+  -> ((t : psi) -> iscontr (A t))
+  -> (a : (t : phi) -> A t)
+  -> (t : psi) -> A t [ phi t |-> a t]
+
+-- [RS17, Proposition 4.8] A (weaker) formulation of function extensionality.
+#def relfunext2 : U
+  := (I : CUBE)
+  -> (psi : I -> TOPE)
+  -> (phi : psi -> TOPE)
+  -> (A : psi -> U)
+  -> (a : (t : phi) -> A t)
+  -> (f : (t : psi) -> A t [ phi t |-> a t ])
+  -> (g : (t : psi) -> A t [ phi t |-> a t ])
+  -> weq (f = g)
+         ((t : psi) -> (f t =_{A t} g t) [ phi t |-> refl ])
+
+-- Restrict extension type to a subshape.
+#def restrict
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \\/ phi t} -> U)
+    (a : {t : I | psi t} -> A t)
+  : {t : I | psi t /\\ phi t} -> A t
+  := \\t -> a t
+
+-- Reformulate extension type as an extension of a restriction.
+#def ext-of-restrict
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \\/ phi t} -> U)
+    (a : {t : I | psi t} -> A t)
+  : (t : psi) -> A t [ psi t /\\ phi t |-> restrict I psi phi A a t ]
+  := a
+
+-- Transform extension of an identity into an identity of restrictions.
+#def restricts-path
+    (r : relfunext2)
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \\/ phi t} -> U)
+    (a_psi : (t : psi) -> A t)
+    (a_phi : (t : phi) -> A t)
+    (e : {t : I | psi t /\\ phi t} -> a_psi t = a_phi t)
+  : restrict I psi phi A a_psi = restrict I phi psi A a_phi
+  := (first (second (r I
+      (\\t -> psi t /\\ phi t)
+      (\\t -> BOT)
+      (\\t -> A t)
+      (\\t -> recBOT)
+      (\\t -> a_psi t)
+      (\\t -> a_phi t)))) e
+
+-- A weaker version of recOR, demanding only a path between a and b:
+-- recOR(psi, phi, a, b) demands that for psi /\\ phi we have a == b (definitionally)
+-- (recId psi phi a b e) demands that e is the proof that a = b (intensionally) for psi /\\ phi
+#def recId
+    (r : relfunext2)
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \\/ phi t} -> U)
+    (a_psi : (t : psi) -> A t)
+    (a_phi : (t : phi) -> A t)
+    (e : {t : I | psi t /\\ phi t} -> a_psi t = a_phi t)
+  : {t : I | psi t \\/ phi t} -> A t
+  := \\t -> recOR(
+        psi t |-> transport
+          ({t : I | psi t /\\ phi t} -> A t)
+          (\\ra -> (t : psi) -> A t [ psi t /\\ phi t |-> ra t])
+          (restrict I psi phi A a_psi)
+          (restrict I phi psi A a_phi)
+          (restricts-path r I psi phi A a_psi a_phi e)
+          (ext-of-restrict I psi phi A a_psi)
+          t,
+        phi t |-> ext-of-restrict I phi psi A a_phi t
+      )
+
+-- If two extension types are equal along two subshapes,
+-- then they are also equal along their union.
+#def id-along-border
+    (r : relfunext2)
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \\/ phi t} -> U)
+    (a b : {t : I | psi t \\/ phi t} -> A t)
+    (e_psi : (t : psi) -> a t = b t)
+    (e_phi : (t : phi) -> a t = b t)
+    (border-is-a-set : {t : I | psi t /\\ phi t} -> isaset (A t))
+  : {t : I | psi t \\/ phi t} -> a t = b t
+  := recId r I psi phi
+        (\\t -> a t = b t)
+        e_psi e_phi
+        (\\t -> border-is-a-set t (a t) (b t) (e_psi t) (e_phi t))
+`
\ No newline at end of file
diff --git a/rzk-playground/components/editor/parser.ts b/rzk-playground/components/editor/parser.ts
new file mode 100644
index 000000000..e3fca9984
--- /dev/null
+++ b/rzk-playground/components/editor/parser.ts
@@ -0,0 +1,32 @@
+import { parser } from 'rzk-lezer/src/parser'
+import { styleTags, tags as t } from '@lezer/highlight'
+import { LRLanguage } from '@codemirror/language'
+
+let parserWithMetadata = parser.configure({
+    props: [
+        styleTags({
+            "LineComment!": t.lineComment,
+            "BlockComment!": t.blockComment,
+            "String!": t.string,
+            "#lang": t.moduleKeyword,
+            "Rzk1!": t.namespace,
+            "#assume #check #compute-nf \
+            #compute-whnf #compute #def #define \
+            #end #postulate #section #set-option \
+            #unset-option #variable #variables": t.definitionKeyword,
+            "β†’ ↦ βˆ‘ Γ— < <= -> =_{ = === > |-> | ∧ ∨ ≑ ≀": t.operatorKeyword,
+            ":": t.definitionOperator,
+            "π₁ Ο€β‚‚ Ξ£ ⊀ βŠ₯ 0_2 0β‚‚ 1_2 1 1β‚‚ 2 \
+            as BOT Cube first idJ recBot recOR \
+            refl_{ refl second Sigma TOP \
+            TOPE U unit Unit uses": t.keyword,
+            "{ }": t.brace,
+            "( )": t.paren,
+            VarIdent: t.variableName
+        })
+    ]
+})
+
+export const language = LRLanguage.define({
+    parser: parserWithMetadata
+})
\ No newline at end of file
diff --git a/rzk-playground/components/editor/theme.ts b/rzk-playground/components/editor/theme.ts
new file mode 100644
index 000000000..c8ee14aeb
--- /dev/null
+++ b/rzk-playground/components/editor/theme.ts
@@ -0,0 +1,247 @@
+import { EditorView } from "@codemirror/view"
+import { Extension } from "@codemirror/state"
+import { HighlightStyle, syntaxHighlighting } from "@codemirror/language"
+import { tags as t } from "@lezer/highlight"
+
+// Using https://github.com/codemirror/theme-one-dark as reference for the styling
+
+// Using https://github.com/codemirror/codemirror5/blob/master/theme/gruvbox-dark.css as a reference for colors
+
+
+const chalky = "#e5c07b",
+    coral = "#e06c75",
+    cyan = "#56b6c2",
+    invalid = "#ffffff",
+    ivory = "#bdae93",
+    stone = "#7c6f64", // Brightened compared to original to increase contrast
+    gutterColor = "#8d8e88",
+    malibu = "#61afef",
+    sage = "#98c379",
+    whiskey = "#d19a66",
+    violet = "#c678dd",
+    darkBackground = "#21252b",
+    highlightBackground = "#2c313a",
+    background = "#272822",
+    tooltipBackground = "#353a42",
+    cursor = "#ebdbb2",
+    activeLine = "#3e3d32",
+    selection = "#49483e",
+    gutterBackground = "#2f3129",
+    textColor = "#ffffff",
+    parenColor = "#eeff00",
+    commentColor = "#909570"
+
+/// The colors used in the theme, as CSS color strings.
+export const color = {
+    chalky,
+    coral,
+    cyan,
+    invalid,
+    ivory,
+    stone,
+    malibu,
+    sage,
+    whiskey,
+    violet,
+    darkBackground,
+    highlightBackground,
+    background,
+    tooltipBackground,
+    selection,
+    cursor,
+    gutterBackground,
+    activeLine
+}
+
+/// The editor theme styles for One Dark.
+export const oneDarkTheme = EditorView.theme({
+    "&": {
+        color: textColor,
+        backgroundColor: background,
+        fontSize: "16px",
+        fontFamily: "Inconsolata"
+    },
+
+    ".cm-content": {
+        caretColor: cursor
+    },
+
+    ".cm-scroller": {
+        lineHeight: "1.2"
+    },
+
+    ".cm-cursor, .cm-dropCursor": { borderLeftColor: cursor },
+    "&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection": { backgroundColor: selection },
+
+    ".cm-panels": { backgroundColor: darkBackground, color: ivory },
+    ".cm-panels.cm-panels-top": { borderBottom: "2px solid black" },
+    ".cm-panels.cm-panels-bottom": { borderTop: "2px solid black" },
+
+
+    ".cm-activeLine": { backgroundColor: activeLine },
+
+    ".cm-searchMatch": {
+        backgroundColor: "#72a1ff59",
+        outline: "1px solid #457dff"
+    },
+    ".cm-searchMatch.cm-searchMatch-selected": {
+        backgroundColor: "#6199ff2f"
+    },
+
+    ".cm-selectionMatch": { backgroundColor: "#aafe661a" },
+
+    "&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket": {
+        backgroundColor: "#bad0f847"
+    },
+
+    ".cm-gutters": {
+        backgroundColor: gutterBackground,
+        color: gutterColor,
+        border: "none",
+        fontWeight: "500"
+    },
+
+    ".cm-activeLineGutter": {
+        backgroundColor: gutterBackground,
+        color: "#d0d2c0"
+    },
+
+    ".cm-foldPlaceholder": {
+        backgroundColor: "transparent",
+        border: "none",
+        color: "#ddd"
+    },
+
+    ".cm-tooltip": {
+        border: "none",
+        backgroundColor: tooltipBackground
+    },
+    ".cm-tooltip .cm-tooltip-arrow:before": {
+        borderTopColor: "transparent",
+        borderBottomColor: "transparent"
+    },
+    ".cm-tooltip .cm-tooltip-arrow:after": {
+        borderTopColor: tooltipBackground,
+        borderBottomColor: tooltipBackground
+    },
+    ".cm-tooltip-autocomplete": {
+        "& > ul > li[aria-selected]": {
+            backgroundColor: highlightBackground,
+            color: ivory
+        }
+    }
+}, { dark: true })
+
+/// The highlighting style for code in the One Dark theme.
+export const oneDarkHighlightStyle = HighlightStyle.define([
+    {
+        tag: t.keyword,
+        color: violet
+    },
+    {
+        tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
+        color: coral
+    },
+    {
+        tag: [t.function(t.variableName), t.labelName],
+        color: malibu
+    },
+    {
+        tag: [t.color, t.constant(t.name), t.standard(t.name)],
+        color: whiskey
+    },
+    {
+        tag: [t.definition(t.name), t.separator],
+        color: ivory
+    },
+    {
+        tag: [t.typeName, t.className, t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
+        color: chalky
+    },
+    {
+        tag: [t.operator, t.operatorKeyword, t.url, t.escape, t.regexp, t.link, t.special(t.string)],
+        color: cyan
+    },
+    {
+        tag: [t.meta, t.comment],
+        color: stone
+    },
+    {
+        tag: t.strong,
+        fontWeight: "bold"
+    },
+    {
+        tag: t.emphasis,
+        fontStyle: "italic"
+    },
+    {
+        tag: t.strikethrough,
+        textDecoration: "line-through"
+    },
+    {
+        tag: t.link,
+        color: stone,
+        textDecoration: "underline"
+    },
+    {
+        tag: t.heading,
+        fontWeight: "bold",
+        color: coral
+    },
+    {
+        tag: t.moduleKeyword,
+        fontWeight: "bold",
+        color: "#178b8b"
+    },
+    {
+        tag: t.namespace,
+        fontWeight: "bold",
+        color: "#fe2f96"
+    },
+    {
+        tag: t.definitionKeyword,
+        fontWeight: "bold",
+        color: "#861ffb"
+    },
+    {
+        tag: t.definitionOperator,
+        fontWeight: "bold",
+        color: "#1fcbfb"
+    },
+    {
+        tag: t.lineComment,
+        color: commentColor
+    },
+    {
+        tag: t.blockComment,
+        color: commentColor
+    },
+    {
+        tag: [t.atom, t.bool, t.special(t.variableName)],
+        color: whiskey
+    },
+    {
+        tag: [t.processingInstruction, t.string, t.inserted],
+        color: sage
+    },
+    {
+        tag: t.brace,
+        color: cyan
+    },
+    {
+        tag: t.paren,
+        color: parenColor
+    },
+    {
+        tag: t.invalid,
+        color: invalid
+    },
+    {
+        tag: t.macroName,
+        color: whiskey,
+    }
+])
+
+/// Extension to enable the One Dark theme (both the editor theme and
+/// the highlight style).
+export const oneDark: Extension = [oneDarkTheme, syntaxHighlighting(oneDarkHighlightStyle)]
\ No newline at end of file
diff --git a/rzk-playground/next.config.js b/rzk-playground/next.config.js
new file mode 100644
index 000000000..ba0d39df6
--- /dev/null
+++ b/rzk-playground/next.config.js
@@ -0,0 +1,7 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+    output: 'export',
+    basePath: ''
+}
+
+module.exports = nextConfig
diff --git a/rzk-playground/package-lock.json b/rzk-playground/package-lock.json
new file mode 100644
index 000000000..a36eadfdb
--- /dev/null
+++ b/rzk-playground/package-lock.json
@@ -0,0 +1,4405 @@
+{
+  "name": "rzk-playground",
+  "version": "0.1.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "rzk-playground",
+      "version": "0.1.0",
+      "dependencies": {
+        "@types/node": "^20.6.3",
+        "@types/react": "^18.2.22",
+        "@types/react-dom": "^18.2.7",
+        "@uiw/react-codemirror": "^4.21.18",
+        "next": "^13.5.2",
+        "re-resizable": "^6.9.11",
+        "react": "^18.2.0",
+        "react-dom": "^18.2.0",
+        "react-keybinds": "^1.0.8",
+        "react-resizable": "^3.0.5",
+        "rzk-lezer": "./rzk-lezer"
+      },
+      "devDependencies": {
+        "@types/react-resizable": "^3.0.4",
+        "eslint": "^8.49.0",
+        "eslint-config-next": "^13.5.2",
+        "eslint-config-prettier": "^9.0.0",
+        "typescript": "^5.2.2"
+      }
+    },
+    "node_modules/@aashutoshrathi/word-wrap": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+      "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
+      "dependencies": {
+        "regenerator-runtime": "^0.14.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@codemirror/autocomplete": {
+      "version": "6.9.1",
+      "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.9.1.tgz",
+      "integrity": "sha512-yma56tqD7khIZK4gy4X5lX3/k5ArMiCGat7HEWRF/8L2kqOjVdp2qKZqpcJjwTIjSj6fqKAHqi7IjtH3QFE+Bw==",
+      "dependencies": {
+        "@codemirror/language": "^6.0.0",
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.17.0",
+        "@lezer/common": "^1.0.0"
+      },
+      "peerDependencies": {
+        "@codemirror/language": "^6.0.0",
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.0.0",
+        "@lezer/common": "^1.0.0"
+      }
+    },
+    "node_modules/@codemirror/commands": {
+      "version": "6.2.5",
+      "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.5.tgz",
+      "integrity": "sha512-dSi7ow2P2YgPBZflR9AJoaTHvqmeGIgkhignYMd5zK5y6DANTvxKxp6eMEpIDUJkRAaOY/TFZ4jP1ADIO/GLVA==",
+      "dependencies": {
+        "@codemirror/language": "^6.0.0",
+        "@codemirror/state": "^6.2.0",
+        "@codemirror/view": "^6.0.0",
+        "@lezer/common": "^1.0.0"
+      }
+    },
+    "node_modules/@codemirror/language": {
+      "version": "6.9.1",
+      "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.1.tgz",
+      "integrity": "sha512-lWRP3Y9IUdOms6DXuBpoWwjkR7yRmnS0hKYCbSfPz9v6Em1A1UCRujAkDiCrdYfs1Z0Eu4dGtwovNPStIfkgNA==",
+      "dependencies": {
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.0.0",
+        "@lezer/common": "^1.1.0",
+        "@lezer/highlight": "^1.0.0",
+        "@lezer/lr": "^1.0.0",
+        "style-mod": "^4.0.0"
+      }
+    },
+    "node_modules/@codemirror/lint": {
+      "version": "6.4.2",
+      "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.2.tgz",
+      "integrity": "sha512-wzRkluWb1ptPKdzlsrbwwjYCPLgzU6N88YBAmlZi8WFyuiEduSd05MnJYNogzyc8rPK7pj6m95ptUApc8sHKVA==",
+      "dependencies": {
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.0.0",
+        "crelt": "^1.0.5"
+      }
+    },
+    "node_modules/@codemirror/search": {
+      "version": "6.5.4",
+      "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.4.tgz",
+      "integrity": "sha512-YoTrvjv9e8EbPs58opjZKyJ3ewFrVSUzQ/4WXlULQLSDDr1nGPJ67mMXFNNVYwdFhybzhrzrtqgHmtpJwIF+8g==",
+      "dependencies": {
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.0.0",
+        "crelt": "^1.0.5"
+      }
+    },
+    "node_modules/@codemirror/state": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz",
+      "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw=="
+    },
+    "node_modules/@codemirror/theme-one-dark": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
+      "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
+      "dependencies": {
+        "@codemirror/language": "^6.0.0",
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.0.0",
+        "@lezer/highlight": "^1.0.0"
+      }
+    },
+    "node_modules/@codemirror/view": {
+      "version": "6.20.0",
+      "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.20.0.tgz",
+      "integrity": "sha512-N+lSr/UybTnSnvSLjzbAWe600x3DhBj3Lerk/BMllB6wDMzgW6OgNI/5eOGnbBAwY8lxxyHQmv/R5ER35nlVmg==",
+      "dependencies": {
+        "@codemirror/state": "^6.1.4",
+        "style-mod": "^4.1.0",
+        "w3c-keyname": "^2.2.4"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
+      "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
+      "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
+      "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
+      "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
+      "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
+      "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
+      "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
+      "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
+      "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
+      "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
+      "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
+      "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
+      "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
+      "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
+      "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
+      "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
+      "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
+      "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
+      "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
+      "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
+      "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
+      "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+      "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+      "dev": true,
+      "dependencies": {
+        "eslint-visitor-keys": "^3.3.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+      }
+    },
+    "node_modules/@eslint-community/regexpp": {
+      "version": "4.8.1",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz",
+      "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==",
+      "dev": true,
+      "engines": {
+        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@eslint/eslintrc": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
+      "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
+      "dev": true,
+      "dependencies": {
+        "ajv": "^6.12.4",
+        "debug": "^4.3.2",
+        "espree": "^9.6.0",
+        "globals": "^13.19.0",
+        "ignore": "^5.2.0",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^4.1.0",
+        "minimatch": "^3.1.2",
+        "strip-json-comments": "^3.1.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint/js": {
+      "version": "8.49.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz",
+      "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@humanwhocodes/config-array": {
+      "version": "0.11.11",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
+      "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==",
+      "dev": true,
+      "dependencies": {
+        "@humanwhocodes/object-schema": "^1.2.1",
+        "debug": "^4.1.1",
+        "minimatch": "^3.0.5"
+      },
+      "engines": {
+        "node": ">=10.10.0"
+      }
+    },
+    "node_modules/@humanwhocodes/module-importer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.22"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/object-schema": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+      "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+      "dev": true
+    },
+    "node_modules/@lezer-unofficial/printer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@lezer-unofficial/printer/-/printer-1.0.1.tgz",
+      "integrity": "sha512-0bIixSdtdCyErXna3eKArYFsGfsUiXrgdu7t4gV8mL+2ooVDQArz66py1lSaEpfYI6n2nO11uNyHHvXojUWakw==",
+      "dev": true,
+      "dependencies": {
+        "@codemirror/state": "^6.2.1",
+        "@lezer/common": "^1.1.0"
+      }
+    },
+    "node_modules/@lezer/common": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.0.tgz",
+      "integrity": "sha512-XPIN3cYDXsoJI/oDWoR2tD++juVrhgIago9xyKhZ7IhGlzdDM9QgC8D8saKNCz5pindGcznFr2HBSsEQSWnSjw=="
+    },
+    "node_modules/@lezer/generator": {
+      "version": "1.5.1",
+      "resolved": "git+ssh://git@github.com/deemp/generator.git#cc38c10ab0d9d6e9b0e6daf1659e7a15dad86649",
+      "integrity": "sha512-r2wTPQgpGKFSMyRo7hAa8PaSg3XVcmkX7PCnSWlXoK4d3Y6ZHTNbLD1cdczmrO1D+fLPMimtIcjgYiXQKnVRHQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@lezer/common": "^1.1.0",
+        "@lezer/lr": "^1.3.0"
+      },
+      "bin": {
+        "lezer-generator": "src/lezer-generator.cjs"
+      }
+    },
+    "node_modules/@lezer/highlight": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.6.tgz",
+      "integrity": "sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==",
+      "dependencies": {
+        "@lezer/common": "^1.0.0"
+      }
+    },
+    "node_modules/@lezer/lr": {
+      "version": "1.3.12",
+      "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.12.tgz",
+      "integrity": "sha512-5nwY1JzCueUdRtlMBnlf1SUi69iGCq2ABq7WQFQMkn/kxPvoACAEnTp4P17CtXxYr7WCwtYPLL2AEvxKPuF1OQ==",
+      "dependencies": {
+        "@lezer/common": "^1.0.0"
+      }
+    },
+    "node_modules/@next/env": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.2.tgz",
+      "integrity": "sha512-dUseBIQVax+XtdJPzhwww4GetTjlkRSsXeQnisIJWBaHsnxYcN2RGzsPHi58D6qnkATjnhuAtQTJmR1hKYQQPg=="
+    },
+    "node_modules/@next/eslint-plugin-next": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.5.2.tgz",
+      "integrity": "sha512-Ew8DOUerJYGRo8pI84SVwn9wxxx8sH92AanCXSkkLJM2W0RJEWy+BqWSCfrlA/3ZIczEl4l4o4lOeTGBPYfBJg==",
+      "dev": true,
+      "dependencies": {
+        "glob": "7.1.7"
+      }
+    },
+    "node_modules/@next/swc-darwin-arm64": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.2.tgz",
+      "integrity": "sha512-7eAyunAWq6yFwdSQliWMmGhObPpHTesiKxMw4DWVxhm5yLotBj8FCR4PXGkpRP2tf8QhaWuVba+/fyAYggqfQg==",
+      "cpu": [
+        "arm64"
+      ],
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-darwin-x64": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.2.tgz",
+      "integrity": "sha512-WxXYWE7zF1ch8rrNh5xbIWzhMVas6Vbw+9BCSyZvu7gZC5EEiyZNJsafsC89qlaSA7BnmsDXVWQmc+s1feSYbQ==",
+      "cpu": [
+        "x64"
+      ],
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-linux-arm64-gnu": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.2.tgz",
+      "integrity": "sha512-URSwhRYrbj/4MSBjLlefPTK3/tvg95TTm6mRaiZWBB6Za3hpHKi8vSdnCMw5D2aP6k0sQQIEG6Pzcfwm+C5vrg==",
+      "cpu": [
+        "arm64"
+      ],
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-linux-arm64-musl": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.2.tgz",
+      "integrity": "sha512-HefiwAdIygFyNmyVsQeiJp+j8vPKpIRYDlmTlF9/tLdcd3qEL/UEBswa1M7cvO8nHcr27ZTKXz5m7dkd56/Esg==",
+      "cpu": [
+        "arm64"
+      ],
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-linux-x64-gnu": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.2.tgz",
+      "integrity": "sha512-htGVVroW0tdHgMYwKWkxWvVoG2RlAdDXRO1RQxYDvOBQsaV0nZsgKkw0EJJJ3urTYnwKskn/MXm305cOgRxD2w==",
+      "cpu": [
+        "x64"
+      ],
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-linux-x64-musl": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.2.tgz",
+      "integrity": "sha512-UBD333GxbHVGi7VDJPPDD1bKnx30gn2clifNJbla7vo5nmBV+x5adyARg05RiT9amIpda6yzAEEUu+s774ldkw==",
+      "cpu": [
+        "x64"
+      ],
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-win32-arm64-msvc": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.2.tgz",
+      "integrity": "sha512-Em9ApaSFIQnWXRT3K6iFnr9uBXymixLc65Xw4eNt7glgH0eiXpg+QhjmgI2BFyc7k4ZIjglfukt9saNpEyolWA==",
+      "cpu": [
+        "arm64"
+      ],
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-win32-ia32-msvc": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.2.tgz",
+      "integrity": "sha512-TBACBvvNYU+87X0yklSuAseqdpua8m/P79P0SG1fWUvWDDA14jASIg7kr86AuY5qix47nZLEJ5WWS0L20jAUNw==",
+      "cpu": [
+        "ia32"
+      ],
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@next/swc-win32-x64-msvc": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.2.tgz",
+      "integrity": "sha512-LfTHt+hTL8w7F9hnB3H4nRasCzLD/fP+h4/GUVBTxrkMJOnh/7OZ0XbYDKO/uuWwryJS9kZjhxcruBiYwc5UDw==",
+      "cpu": [
+        "x64"
+      ],
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@rushstack/eslint-patch": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.4.0.tgz",
+      "integrity": "sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg==",
+      "dev": true
+    },
+    "node_modules/@swc/helpers": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
+      "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
+      "dependencies": {
+        "tslib": "^2.4.0"
+      }
+    },
+    "node_modules/@types/json5": {
+      "version": "0.0.29",
+      "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+      "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+      "dev": true
+    },
+    "node_modules/@types/node": {
+      "version": "20.6.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz",
+      "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA=="
+    },
+    "node_modules/@types/prop-types": {
+      "version": "15.7.6",
+      "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.6.tgz",
+      "integrity": "sha512-RK/kBbYOQQHLYj9Z95eh7S6t7gq4Ojt/NT8HTk8bWVhA5DaF+5SMnxHKkP4gPNN3wAZkKP+VjAf0ebtYzf+fxg=="
+    },
+    "node_modules/@types/react": {
+      "version": "18.2.22",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.22.tgz",
+      "integrity": "sha512-60fLTOLqzarLED2O3UQImc/lsNRgG0jE/a1mPW9KjMemY0LMITWEsbS4VvZ4p6rorEHd5YKxxmMKSDK505GHpA==",
+      "dependencies": {
+        "@types/prop-types": "*",
+        "@types/scheduler": "*",
+        "csstype": "^3.0.2"
+      }
+    },
+    "node_modules/@types/react-dom": {
+      "version": "18.2.7",
+      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
+      "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
+      "dependencies": {
+        "@types/react": "*"
+      }
+    },
+    "node_modules/@types/react-resizable": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/@types/react-resizable/-/react-resizable-3.0.4.tgz",
+      "integrity": "sha512-+QguN9CDfC1lthq+4noG1fkxh8cqkV2Fv/Mu3mdknCCBiwwNLecnBdk1MmNNN7uJpT23Nx/aVkYsbt5NuWouFw==",
+      "dev": true,
+      "dependencies": {
+        "@types/react": "*"
+      }
+    },
+    "node_modules/@types/scheduler": {
+      "version": "0.16.3",
+      "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
+      "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ=="
+    },
+    "node_modules/@typescript-eslint/parser": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz",
+      "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/scope-manager": "6.7.2",
+        "@typescript-eslint/types": "6.7.2",
+        "@typescript-eslint/typescript-estree": "6.7.2",
+        "@typescript-eslint/visitor-keys": "6.7.2",
+        "debug": "^4.3.4"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^7.0.0 || ^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/scope-manager": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz",
+      "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "6.7.2",
+        "@typescript-eslint/visitor-keys": "6.7.2"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/types": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz",
+      "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==",
+      "dev": true,
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz",
+      "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "6.7.2",
+        "@typescript-eslint/visitor-keys": "6.7.2",
+        "debug": "^4.3.4",
+        "globby": "^11.1.0",
+        "is-glob": "^4.0.3",
+        "semver": "^7.5.4",
+        "ts-api-utils": "^1.0.1"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@typescript-eslint/visitor-keys": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz",
+      "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==",
+      "dev": true,
+      "dependencies": {
+        "@typescript-eslint/types": "6.7.2",
+        "eslint-visitor-keys": "^3.4.1"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@uiw/codemirror-extensions-basic-setup": {
+      "version": "4.21.18",
+      "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.21.18.tgz",
+      "integrity": "sha512-D/vUMq62VPectfrC+Kyw3mtkmxx1/cotVrVDZER/knicx5tyHaqyt06sOZOezhgeo75WKpmjNaRrUZSoCWnGGQ==",
+      "dependencies": {
+        "@codemirror/autocomplete": "^6.0.0",
+        "@codemirror/commands": "^6.0.0",
+        "@codemirror/language": "^6.0.0",
+        "@codemirror/lint": "^6.0.0",
+        "@codemirror/search": "^6.0.0",
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.0.0"
+      },
+      "peerDependencies": {
+        "@codemirror/autocomplete": ">=6.0.0",
+        "@codemirror/commands": ">=6.0.0",
+        "@codemirror/language": ">=6.0.0",
+        "@codemirror/lint": ">=6.0.0",
+        "@codemirror/search": ">=6.0.0",
+        "@codemirror/state": ">=6.0.0",
+        "@codemirror/view": ">=6.0.0"
+      }
+    },
+    "node_modules/@uiw/react-codemirror": {
+      "version": "4.21.18",
+      "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.21.18.tgz",
+      "integrity": "sha512-ZjDMdjH28/eaG2EEqq8+yVnKOrthicu+0UHlCTUa4DHirYfb0RTIcsDXGDBZByvWP9Cglc74PGdS5PuCjEdTgg==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.6",
+        "@codemirror/commands": "^6.1.0",
+        "@codemirror/state": "^6.1.1",
+        "@codemirror/theme-one-dark": "^6.0.0",
+        "@uiw/codemirror-extensions-basic-setup": "4.21.18",
+        "codemirror": "^6.0.0"
+      },
+      "peerDependencies": {
+        "@babel/runtime": ">=7.11.0",
+        "@codemirror/state": ">=6.0.0",
+        "@codemirror/theme-one-dark": ">=6.0.0",
+        "@codemirror/view": ">=6.0.0",
+        "codemirror": ">=6.0.0",
+        "react": ">=16.8.0",
+        "react-dom": ">=16.8.0"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.10.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+      "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+      "dev": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-jsx": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+      "dev": true,
+      "peerDependencies": {
+        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dev": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "node_modules/aria-query": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+      "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+      "dev": true,
+      "dependencies": {
+        "dequal": "^2.0.3"
+      }
+    },
+    "node_modules/array-buffer-byte-length": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+      "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "is-array-buffer": "^3.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array-includes": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
+      "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "is-string": "^1.0.7"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/array.prototype.findlastindex": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz",
+      "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0",
+        "get-intrinsic": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array.prototype.flat": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+      "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array.prototype.flatmap": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+      "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array.prototype.tosorted": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz",
+      "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0",
+        "get-intrinsic": "^1.2.1"
+      }
+    },
+    "node_modules/arraybuffer.prototype.slice": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
+      "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+      "dev": true,
+      "dependencies": {
+        "array-buffer-byte-length": "^1.0.0",
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "is-array-buffer": "^3.0.2",
+        "is-shared-array-buffer": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/ast-types-flow": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+      "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
+      "dev": true
+    },
+    "node_modules/asynciterator.prototype": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
+      "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
+      "dev": true,
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      }
+    },
+    "node_modules/available-typed-arrays": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+      "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/axe-core": {
+      "version": "4.8.2",
+      "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.2.tgz",
+      "integrity": "sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/axobject-query": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
+      "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
+      "dev": true,
+      "dependencies": {
+        "dequal": "^2.0.3"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "dependencies": {
+        "fill-range": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "dev": true
+    },
+    "node_modules/busboy": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+      "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+      "dependencies": {
+        "streamsearch": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=10.16.0"
+      }
+    },
+    "node_modules/call-bind": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001538",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz",
+      "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ]
+    },
+    "node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/client-only": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+      "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+    },
+    "node_modules/clsx": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+      "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/codemirror": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
+      "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
+      "dependencies": {
+        "@codemirror/autocomplete": "^6.0.0",
+        "@codemirror/commands": "^6.0.0",
+        "@codemirror/language": "^6.0.0",
+        "@codemirror/lint": "^6.0.0",
+        "@codemirror/search": "^6.0.0",
+        "@codemirror/state": "^6.0.0",
+        "@codemirror/view": "^6.0.0"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "dev": true
+    },
+    "node_modules/crelt": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
+      "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+      "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
+    },
+    "node_modules/damerau-levenshtein": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+      "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+      "dev": true
+    },
+    "node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deep-is": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+      "dev": true
+    },
+    "node_modules/define-data-property": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz",
+      "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.2.1",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/define-properties": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+      "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.0.1",
+        "has-property-descriptors": "^1.0.0",
+        "object-keys": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/dequal": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+      "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "dependencies": {
+        "path-type": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/doctrine": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/emoji-regex": {
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+      "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+      "dev": true
+    },
+    "node_modules/enhanced-resolve": {
+      "version": "5.15.0",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
+      "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/es-abstract": {
+      "version": "1.22.2",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz",
+      "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==",
+      "dev": true,
+      "dependencies": {
+        "array-buffer-byte-length": "^1.0.0",
+        "arraybuffer.prototype.slice": "^1.0.2",
+        "available-typed-arrays": "^1.0.5",
+        "call-bind": "^1.0.2",
+        "es-set-tostringtag": "^2.0.1",
+        "es-to-primitive": "^1.2.1",
+        "function.prototype.name": "^1.1.6",
+        "get-intrinsic": "^1.2.1",
+        "get-symbol-description": "^1.0.0",
+        "globalthis": "^1.0.3",
+        "gopd": "^1.0.1",
+        "has": "^1.0.3",
+        "has-property-descriptors": "^1.0.0",
+        "has-proto": "^1.0.1",
+        "has-symbols": "^1.0.3",
+        "internal-slot": "^1.0.5",
+        "is-array-buffer": "^3.0.2",
+        "is-callable": "^1.2.7",
+        "is-negative-zero": "^2.0.2",
+        "is-regex": "^1.1.4",
+        "is-shared-array-buffer": "^1.0.2",
+        "is-string": "^1.0.7",
+        "is-typed-array": "^1.1.12",
+        "is-weakref": "^1.0.2",
+        "object-inspect": "^1.12.3",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.4",
+        "regexp.prototype.flags": "^1.5.1",
+        "safe-array-concat": "^1.0.1",
+        "safe-regex-test": "^1.0.0",
+        "string.prototype.trim": "^1.2.8",
+        "string.prototype.trimend": "^1.0.7",
+        "string.prototype.trimstart": "^1.0.7",
+        "typed-array-buffer": "^1.0.0",
+        "typed-array-byte-length": "^1.0.0",
+        "typed-array-byte-offset": "^1.0.0",
+        "typed-array-length": "^1.0.4",
+        "unbox-primitive": "^1.0.2",
+        "which-typed-array": "^1.1.11"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/es-iterator-helpers": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz",
+      "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==",
+      "dev": true,
+      "dependencies": {
+        "asynciterator.prototype": "^1.0.0",
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.22.1",
+        "es-set-tostringtag": "^2.0.1",
+        "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.2.1",
+        "globalthis": "^1.0.3",
+        "has-property-descriptors": "^1.0.0",
+        "has-proto": "^1.0.1",
+        "has-symbols": "^1.0.3",
+        "internal-slot": "^1.0.5",
+        "iterator.prototype": "^1.1.2",
+        "safe-array-concat": "^1.0.1"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+      "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.1.3",
+        "has": "^1.0.3",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-shim-unscopables": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+      "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+      "dev": true,
+      "dependencies": {
+        "has": "^1.0.3"
+      }
+    },
+    "node_modules/es-to-primitive": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+      "dev": true,
+      "dependencies": {
+        "is-callable": "^1.1.4",
+        "is-date-object": "^1.0.1",
+        "is-symbol": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
+      "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/android-arm": "0.18.20",
+        "@esbuild/android-arm64": "0.18.20",
+        "@esbuild/android-x64": "0.18.20",
+        "@esbuild/darwin-arm64": "0.18.20",
+        "@esbuild/darwin-x64": "0.18.20",
+        "@esbuild/freebsd-arm64": "0.18.20",
+        "@esbuild/freebsd-x64": "0.18.20",
+        "@esbuild/linux-arm": "0.18.20",
+        "@esbuild/linux-arm64": "0.18.20",
+        "@esbuild/linux-ia32": "0.18.20",
+        "@esbuild/linux-loong64": "0.18.20",
+        "@esbuild/linux-mips64el": "0.18.20",
+        "@esbuild/linux-ppc64": "0.18.20",
+        "@esbuild/linux-riscv64": "0.18.20",
+        "@esbuild/linux-s390x": "0.18.20",
+        "@esbuild/linux-x64": "0.18.20",
+        "@esbuild/netbsd-x64": "0.18.20",
+        "@esbuild/openbsd-x64": "0.18.20",
+        "@esbuild/sunos-x64": "0.18.20",
+        "@esbuild/win32-arm64": "0.18.20",
+        "@esbuild/win32-ia32": "0.18.20",
+        "@esbuild/win32-x64": "0.18.20"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint": {
+      "version": "8.49.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz",
+      "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==",
+      "dev": true,
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/regexpp": "^4.6.1",
+        "@eslint/eslintrc": "^2.1.2",
+        "@eslint/js": "8.49.0",
+        "@humanwhocodes/config-array": "^0.11.11",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@nodelib/fs.walk": "^1.2.8",
+        "ajv": "^6.12.4",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.2",
+        "debug": "^4.3.2",
+        "doctrine": "^3.0.0",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^7.2.2",
+        "eslint-visitor-keys": "^3.4.3",
+        "espree": "^9.6.1",
+        "esquery": "^1.4.2",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^6.0.1",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "globals": "^13.19.0",
+        "graphemer": "^1.4.0",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "is-path-inside": "^3.0.3",
+        "js-yaml": "^4.1.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.4.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3",
+        "strip-ansi": "^6.0.1",
+        "text-table": "^0.2.0"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-config-next": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.5.2.tgz",
+      "integrity": "sha512-kCF7k7fHBtFtxfP6J6AP6Mo0vW3CrFeoIuoZ7NHGIvLFc/RUaIspJ6inO/R33zE1o9t/lbJgTnsqnRB++sxCUQ==",
+      "dev": true,
+      "dependencies": {
+        "@next/eslint-plugin-next": "13.5.2",
+        "@rushstack/eslint-patch": "^1.3.3",
+        "@typescript-eslint/parser": "^5.4.2 || ^6.0.0",
+        "eslint-import-resolver-node": "^0.3.6",
+        "eslint-import-resolver-typescript": "^3.5.2",
+        "eslint-plugin-import": "^2.28.1",
+        "eslint-plugin-jsx-a11y": "^6.7.1",
+        "eslint-plugin-react": "^7.33.2",
+        "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+      },
+      "peerDependencies": {
+        "eslint": "^7.23.0 || ^8.0.0",
+        "typescript": ">=3.3.1"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint-config-prettier": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
+      "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
+      "dev": true,
+      "bin": {
+        "eslint-config-prettier": "bin/cli.js"
+      },
+      "peerDependencies": {
+        "eslint": ">=7.0.0"
+      }
+    },
+    "node_modules/eslint-import-resolver-node": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+      "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^3.2.7",
+        "is-core-module": "^2.13.0",
+        "resolve": "^1.22.4"
+      }
+    },
+    "node_modules/eslint-import-resolver-node/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/eslint-import-resolver-typescript": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.0.tgz",
+      "integrity": "sha512-QTHR9ddNnn35RTxlaEnx2gCxqFlF2SEN0SE2d17SqwyM7YOSI2GHWRYp5BiRkObTUNYPupC/3Fq2a0PpT+EKpg==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.3.4",
+        "enhanced-resolve": "^5.12.0",
+        "eslint-module-utils": "^2.7.4",
+        "fast-glob": "^3.3.1",
+        "get-tsconfig": "^4.5.0",
+        "is-core-module": "^2.11.0",
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
+      },
+      "peerDependencies": {
+        "eslint": "*",
+        "eslint-plugin-import": "*"
+      }
+    },
+    "node_modules/eslint-module-utils": {
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
+      "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^3.2.7"
+      },
+      "engines": {
+        "node": ">=4"
+      },
+      "peerDependenciesMeta": {
+        "eslint": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint-module-utils/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/eslint-plugin-import": {
+      "version": "2.28.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz",
+      "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==",
+      "dev": true,
+      "dependencies": {
+        "array-includes": "^3.1.6",
+        "array.prototype.findlastindex": "^1.2.2",
+        "array.prototype.flat": "^1.3.1",
+        "array.prototype.flatmap": "^1.3.1",
+        "debug": "^3.2.7",
+        "doctrine": "^2.1.0",
+        "eslint-import-resolver-node": "^0.3.7",
+        "eslint-module-utils": "^2.8.0",
+        "has": "^1.0.3",
+        "is-core-module": "^2.13.0",
+        "is-glob": "^4.0.3",
+        "minimatch": "^3.1.2",
+        "object.fromentries": "^2.0.6",
+        "object.groupby": "^1.0.0",
+        "object.values": "^1.1.6",
+        "semver": "^6.3.1",
+        "tsconfig-paths": "^3.14.2"
+      },
+      "engines": {
+        "node": ">=4"
+      },
+      "peerDependencies": {
+        "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+      }
+    },
+    "node_modules/eslint-plugin-import/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/eslint-plugin-import/node_modules/doctrine": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/eslint-plugin-import/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/eslint-plugin-jsx-a11y": {
+      "version": "6.7.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz",
+      "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/runtime": "^7.20.7",
+        "aria-query": "^5.1.3",
+        "array-includes": "^3.1.6",
+        "array.prototype.flatmap": "^1.3.1",
+        "ast-types-flow": "^0.0.7",
+        "axe-core": "^4.6.2",
+        "axobject-query": "^3.1.1",
+        "damerau-levenshtein": "^1.0.8",
+        "emoji-regex": "^9.2.2",
+        "has": "^1.0.3",
+        "jsx-ast-utils": "^3.3.3",
+        "language-tags": "=1.0.5",
+        "minimatch": "^3.1.2",
+        "object.entries": "^1.1.6",
+        "object.fromentries": "^2.0.6",
+        "semver": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependencies": {
+        "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+      }
+    },
+    "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/eslint-plugin-react": {
+      "version": "7.33.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
+      "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
+      "dev": true,
+      "dependencies": {
+        "array-includes": "^3.1.6",
+        "array.prototype.flatmap": "^1.3.1",
+        "array.prototype.tosorted": "^1.1.1",
+        "doctrine": "^2.1.0",
+        "es-iterator-helpers": "^1.0.12",
+        "estraverse": "^5.3.0",
+        "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+        "minimatch": "^3.1.2",
+        "object.entries": "^1.1.6",
+        "object.fromentries": "^2.0.6",
+        "object.hasown": "^1.1.2",
+        "object.values": "^1.1.6",
+        "prop-types": "^15.8.1",
+        "resolve": "^2.0.0-next.4",
+        "semver": "^6.3.1",
+        "string.prototype.matchall": "^4.0.8"
+      },
+      "engines": {
+        "node": ">=4"
+      },
+      "peerDependencies": {
+        "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+      }
+    },
+    "node_modules/eslint-plugin-react-hooks": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+      "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+      }
+    },
+    "node_modules/eslint-plugin-react/node_modules/doctrine": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/eslint-plugin-react/node_modules/resolve": {
+      "version": "2.0.0-next.4",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
+      "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.9.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/eslint-plugin-react/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "7.2.2",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+      "dev": true,
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/espree": {
+      "version": "9.6.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.9.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^3.4.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esquery": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+      "dev": true,
+      "dependencies": {
+        "estraverse": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "dev": true
+    },
+    "node_modules/fast-glob": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+      "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.4"
+      },
+      "engines": {
+        "node": ">=8.6.0"
+      }
+    },
+    "node_modules/fast-glob/node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "dev": true
+    },
+    "node_modules/fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+      "dev": true
+    },
+    "node_modules/fastq": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+      "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+      "dev": true,
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "node_modules/file-entry-cache": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+      "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+      "dev": true,
+      "dependencies": {
+        "flat-cache": "^3.0.4"
+      },
+      "engines": {
+        "node": "^10.12.0 || >=12.0.0"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dev": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/flat-cache": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz",
+      "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==",
+      "dev": true,
+      "dependencies": {
+        "flatted": "^3.2.7",
+        "keyv": "^4.5.3",
+        "rimraf": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/flatted": {
+      "version": "3.2.9",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+      "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+      "dev": true
+    },
+    "node_modules/for-each": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+      "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+      "dev": true,
+      "dependencies": {
+        "is-callable": "^1.1.3"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "dev": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "node_modules/function.prototype.name": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+      "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "functions-have-names": "^1.2.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/functions-have-names": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+      "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
+      "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1",
+        "has": "^1.0.3",
+        "has-proto": "^1.0.1",
+        "has-symbols": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-symbol-description": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+      "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-tsconfig": {
+      "version": "4.7.2",
+      "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz",
+      "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==",
+      "dev": true,
+      "dependencies": {
+        "resolve-pkg-maps": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.1.7",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "dev": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
+    },
+    "node_modules/globals": {
+      "version": "13.22.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz",
+      "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==",
+      "dev": true,
+      "dependencies": {
+        "type-fest": "^0.20.2"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/globalthis": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+      "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+      "dev": true,
+      "dependencies": {
+        "define-properties": "^1.1.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/globby": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+      "dev": true,
+      "dependencies": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.2.9",
+        "ignore": "^5.2.0",
+        "merge2": "^1.4.1",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+      "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.1.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+    },
+    "node_modules/graphemer": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+      "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+      "dev": true
+    },
+    "node_modules/has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/has-bigints": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+      "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/has-property-descriptors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+      "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.1.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+      "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+      "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+      "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+      "dev": true,
+      "dependencies": {
+        "has-symbols": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/ignore": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/import-fresh": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+      "dev": true,
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "dev": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "node_modules/internal-slot": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+      "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.2.0",
+        "has": "^1.0.3",
+        "side-channel": "^1.0.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/is-array-buffer": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+      "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.2.0",
+        "is-typed-array": "^1.1.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-async-function": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+      "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-bigint": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+      "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+      "dev": true,
+      "dependencies": {
+        "has-bigints": "^1.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-boolean-object": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+      "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-callable": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+      "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.13.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
+      "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
+      "dev": true,
+      "dependencies": {
+        "has": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-date-object": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+      "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-finalizationregistry": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+      "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-generator-function": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+      "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-map": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+      "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-negative-zero": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+      "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-number-object": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+      "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-path-inside": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+      "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-regex": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+      "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-set": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+      "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-shared-array-buffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+      "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-string": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+      "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-symbol": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+      "dev": true,
+      "dependencies": {
+        "has-symbols": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-typed-array": {
+      "version": "1.1.12",
+      "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
+      "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+      "dev": true,
+      "dependencies": {
+        "which-typed-array": "^1.1.11"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakmap": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+      "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakref": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+      "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakset": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+      "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/isarray": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "dev": true
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true
+    },
+    "node_modules/iterator.prototype": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+      "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+      "dev": true,
+      "dependencies": {
+        "define-properties": "^1.2.1",
+        "get-intrinsic": "^1.2.1",
+        "has-symbols": "^1.0.3",
+        "reflect.getprototypeof": "^1.0.4",
+        "set-function-name": "^2.0.1"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+    },
+    "node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/json-buffer": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+      "dev": true
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "node_modules/json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+      "dev": true
+    },
+    "node_modules/json5": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+      "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+      "dev": true,
+      "dependencies": {
+        "minimist": "^1.2.0"
+      },
+      "bin": {
+        "json5": "lib/cli.js"
+      }
+    },
+    "node_modules/jsx-ast-utils": {
+      "version": "3.3.5",
+      "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+      "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+      "dev": true,
+      "dependencies": {
+        "array-includes": "^3.1.6",
+        "array.prototype.flat": "^1.3.1",
+        "object.assign": "^4.1.4",
+        "object.values": "^1.1.6"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/keyv": {
+      "version": "4.5.3",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
+      "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==",
+      "dev": true,
+      "dependencies": {
+        "json-buffer": "3.0.1"
+      }
+    },
+    "node_modules/language-subtag-registry": {
+      "version": "0.3.22",
+      "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+      "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+      "dev": true
+    },
+    "node_modules/language-tags": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
+      "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
+      "dev": true,
+      "dependencies": {
+        "language-subtag-registry": "~0.3.2"
+      }
+    },
+    "node_modules/levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+      "dev": true
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+      "dev": true,
+      "dependencies": {
+        "braces": "^3.0.2",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+      "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+      "dev": true
+    },
+    "node_modules/next": {
+      "version": "13.5.2",
+      "resolved": "https://registry.npmjs.org/next/-/next-13.5.2.tgz",
+      "integrity": "sha512-vog4UhUaMYAzeqfiAAmgB/QWLW7p01/sg+2vn6bqc/CxHFYizMzLv6gjxKzl31EVFkfl/F+GbxlKizlkTE9RdA==",
+      "dependencies": {
+        "@next/env": "13.5.2",
+        "@swc/helpers": "0.5.2",
+        "busboy": "1.6.0",
+        "caniuse-lite": "^1.0.30001406",
+        "postcss": "8.4.14",
+        "styled-jsx": "5.1.1",
+        "watchpack": "2.4.0",
+        "zod": "3.21.4"
+      },
+      "bin": {
+        "next": "dist/bin/next"
+      },
+      "engines": {
+        "node": ">=16.14.0"
+      },
+      "optionalDependencies": {
+        "@next/swc-darwin-arm64": "13.5.2",
+        "@next/swc-darwin-x64": "13.5.2",
+        "@next/swc-linux-arm64-gnu": "13.5.2",
+        "@next/swc-linux-arm64-musl": "13.5.2",
+        "@next/swc-linux-x64-gnu": "13.5.2",
+        "@next/swc-linux-x64-musl": "13.5.2",
+        "@next/swc-win32-arm64-msvc": "13.5.2",
+        "@next/swc-win32-ia32-msvc": "13.5.2",
+        "@next/swc-win32-x64-msvc": "13.5.2"
+      },
+      "peerDependencies": {
+        "@opentelemetry/api": "^1.1.0",
+        "react": "^18.2.0",
+        "react-dom": "^18.2.0",
+        "sass": "^1.3.0"
+      },
+      "peerDependenciesMeta": {
+        "@opentelemetry/api": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.12.3",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+      "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object-keys": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/object.assign": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+      "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.4",
+        "has-symbols": "^1.0.3",
+        "object-keys": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object.entries": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
+      "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/object.fromentries": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
+      "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object.groupby": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz",
+      "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1"
+      }
+    },
+    "node_modules/object.hasown": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz",
+      "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==",
+      "dev": true,
+      "dependencies": {
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object.values": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
+      "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "dev": true,
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/optionator": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+      "dev": true,
+      "dependencies": {
+        "@aashutoshrathi/word-wrap": "^1.2.3",
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.4.14",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
+      "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        }
+      ],
+      "dependencies": {
+        "nanoid": "^3.3.4",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.0.2"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/prelude-ls": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+      "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/re-resizable": {
+      "version": "6.9.11",
+      "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-6.9.11.tgz",
+      "integrity": "sha512-a3hiLWck/NkmyLvGWUuvkAmN1VhwAz4yOhS6FdMTaxCUVN9joIWkT11wsO68coG/iEYuwn+p/7qAmfQzRhiPLQ==",
+      "peerDependencies": {
+        "react": "^16.13.1 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/react": {
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
+      "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
+      "dependencies": {
+        "loose-envify": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-dom": {
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
+      "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "scheduler": "^0.23.0"
+      },
+      "peerDependencies": {
+        "react": "^18.2.0"
+      }
+    },
+    "node_modules/react-draggable": {
+      "version": "4.4.5",
+      "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz",
+      "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
+      "dependencies": {
+        "clsx": "^1.1.1",
+        "prop-types": "^15.8.1"
+      },
+      "peerDependencies": {
+        "react": ">= 16.3.0",
+        "react-dom": ">= 16.3.0"
+      }
+    },
+    "node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
+    "node_modules/react-keybinds": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/react-keybinds/-/react-keybinds-1.0.8.tgz",
+      "integrity": "sha512-1C+vqvxjNzCa49UsIsbe+xJwGnBVsPyDzNROiVqQAj36HV8xxRsx1nrSzcGZ5wb7JC2cM/iO2NxVbWWIcV8cZQ==",
+      "dependencies": {
+        "use-debounce": "^8.0.4"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "react": ">=16"
+      }
+    },
+    "node_modules/react-resizable": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz",
+      "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==",
+      "dependencies": {
+        "prop-types": "15.x",
+        "react-draggable": "^4.0.3"
+      },
+      "peerDependencies": {
+        "react": ">= 16.3"
+      }
+    },
+    "node_modules/reflect.getprototypeof": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
+      "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "globalthis": "^1.0.3",
+        "which-builtin-type": "^1.1.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/regenerator-runtime": {
+      "version": "0.14.0",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+      "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
+    },
+    "node_modules/regexp.prototype.flags": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
+      "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "set-function-name": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.6",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz",
+      "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.13.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/resolve-pkg-maps": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+      "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+      }
+    },
+    "node_modules/reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true,
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "dev": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "node_modules/rzk-lezer": {
+      "resolved": "rzk-lezer",
+      "link": true
+    },
+    "node_modules/safe-array-concat": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
+      "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.2.1",
+        "has-symbols": "^1.0.3",
+        "isarray": "^2.0.5"
+      },
+      "engines": {
+        "node": ">=0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/safe-regex-test": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+      "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.3",
+        "is-regex": "^1.1.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/scheduler": {
+      "version": "0.23.0",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+      "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+      "dependencies": {
+        "loose-envify": "^1.1.0"
+      }
+    },
+    "node_modules/semver": {
+      "version": "7.5.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/set-function-name": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
+      "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.0.1",
+        "functions-have-names": "^1.2.3",
+        "has-property-descriptors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/side-channel": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dev": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/streamsearch": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+      "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/string.prototype.matchall": {
+      "version": "4.0.10",
+      "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
+      "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "has-symbols": "^1.0.3",
+        "internal-slot": "^1.0.5",
+        "regexp.prototype.flags": "^1.5.0",
+        "set-function-name": "^2.0.0",
+        "side-channel": "^1.0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trim": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
+      "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trimend": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
+      "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trimstart": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
+      "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/style-mod": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz",
+      "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA=="
+    },
+    "node_modules/styled-jsx": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
+      "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+      "dependencies": {
+        "client-only": "0.0.1"
+      },
+      "engines": {
+        "node": ">= 12.0.0"
+      },
+      "peerDependencies": {
+        "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+      },
+      "peerDependenciesMeta": {
+        "@babel/core": {
+          "optional": true
+        },
+        "babel-plugin-macros": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/tapable": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+      "dev": true
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/ts-api-utils": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
+      "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
+      "dev": true,
+      "engines": {
+        "node": ">=16.13.0"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.2.0"
+      }
+    },
+    "node_modules/tsconfig-paths": {
+      "version": "3.14.2",
+      "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+      "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+      "dev": true,
+      "dependencies": {
+        "@types/json5": "^0.0.29",
+        "json5": "^1.0.2",
+        "minimist": "^1.2.6",
+        "strip-bom": "^3.0.0"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+    },
+    "node_modules/tsx": {
+      "version": "3.13.0",
+      "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.13.0.tgz",
+      "integrity": "sha512-rjmRpTu3as/5fjNq/kOkOtihgLxuIz6pbKdj9xwP4J5jOLkBxw/rjN5ANw+KyrrOXV5uB7HC8+SrrSJxT65y+A==",
+      "dev": true,
+      "dependencies": {
+        "esbuild": "~0.18.20",
+        "get-tsconfig": "^4.7.2",
+        "source-map-support": "^0.5.21"
+      },
+      "bin": {
+        "tsx": "dist/cli.mjs"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      }
+    },
+    "node_modules/type-check": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/type-fest": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/typed-array-buffer": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
+      "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.2.1",
+        "is-typed-array": "^1.1.10"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/typed-array-byte-length": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+      "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "for-each": "^0.3.3",
+        "has-proto": "^1.0.1",
+        "is-typed-array": "^1.1.10"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typed-array-byte-offset": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+      "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+      "dev": true,
+      "dependencies": {
+        "available-typed-arrays": "^1.0.5",
+        "call-bind": "^1.0.2",
+        "for-each": "^0.3.3",
+        "has-proto": "^1.0.1",
+        "is-typed-array": "^1.1.10"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typed-array-length": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+      "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "for-each": "^0.3.3",
+        "is-typed-array": "^1.1.9"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
+      "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/unbox-primitive": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+      "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-bigints": "^1.0.2",
+        "has-symbols": "^1.0.3",
+        "which-boxed-primitive": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dev": true,
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/use-debounce": {
+      "version": "8.0.4",
+      "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-8.0.4.tgz",
+      "integrity": "sha512-fGqsYQzl8kLHF2QpQSgIwgOgJmnh6j5L6SIzQiHdLfwp3q1egUL3btq5Bg2SJysH6A0ILLgT2IqXZKoNJr0nFw==",
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.8.0"
+      }
+    },
+    "node_modules/w3c-keyname": {
+      "version": "2.2.8",
+      "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+      "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
+    },
+    "node_modules/watchpack": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
+      "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+      "dependencies": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/which-boxed-primitive": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+      "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+      "dev": true,
+      "dependencies": {
+        "is-bigint": "^1.0.1",
+        "is-boolean-object": "^1.1.0",
+        "is-number-object": "^1.0.4",
+        "is-string": "^1.0.5",
+        "is-symbol": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-builtin-type": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+      "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+      "dev": true,
+      "dependencies": {
+        "function.prototype.name": "^1.1.5",
+        "has-tostringtag": "^1.0.0",
+        "is-async-function": "^2.0.0",
+        "is-date-object": "^1.0.5",
+        "is-finalizationregistry": "^1.0.2",
+        "is-generator-function": "^1.0.10",
+        "is-regex": "^1.1.4",
+        "is-weakref": "^1.0.2",
+        "isarray": "^2.0.5",
+        "which-boxed-primitive": "^1.0.2",
+        "which-collection": "^1.0.1",
+        "which-typed-array": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-collection": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+      "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+      "dev": true,
+      "dependencies": {
+        "is-map": "^2.0.1",
+        "is-set": "^2.0.1",
+        "is-weakmap": "^2.0.1",
+        "is-weakset": "^2.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-typed-array": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
+      "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
+      "dev": true,
+      "dependencies": {
+        "available-typed-arrays": "^1.0.5",
+        "call-bind": "^1.0.2",
+        "for-each": "^0.3.3",
+        "gopd": "^1.0.1",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "dev": true
+    },
+    "node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/zod": {
+      "version": "3.21.4",
+      "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
+      "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
+      "funding": {
+        "url": "https://github.com/sponsors/colinhacks"
+      }
+    },
+    "rzk-lezer": {
+      "version": "0.1.0",
+      "dependencies": {
+        "@lezer/lr": "^1.3.12"
+      },
+      "devDependencies": {
+        "@lezer-unofficial/printer": "^1.0.1",
+        "@lezer/generator": "deemp/generator#cc38c10ab0d9d6e9b0e6daf1659e7a15dad86649",
+        "tsx": "^3.13.0"
+      }
+    }
+  }
+}
diff --git a/rzk-playground/package.json b/rzk-playground/package.json
new file mode 100644
index 000000000..8f15166e0
--- /dev/null
+++ b/rzk-playground/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "rzk-playground",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "dev": "next dev",
+    "build": "next build",
+    "start": "next start",
+    "lint": "next lint"
+  },
+  "dependencies": {
+    "@types/node": "^20.6.3",
+    "@types/react": "^18.2.22",
+    "@types/react-dom": "^18.2.7",
+    "@uiw/react-codemirror": "^4.21.18",
+    "next": "^13.5.2",
+    "re-resizable": "^6.9.11",
+    "react": "^18.2.0",
+    "react-dom": "^18.2.0",
+    "react-keybinds": "^1.0.8",
+    "react-resizable": "^3.0.5",
+    "rzk-lezer": "./rzk-lezer"
+  },
+  "devDependencies": {
+    "eslint": "^8.49.0",
+    "eslint-config-next": "^13.5.2",
+    "typescript": "^5.2.2",
+    "@types/react-resizable": "^3.0.4",
+    "eslint-config-prettier": "^9.0.0"
+  }
+}
diff --git a/rzk-playground/rzk-lezer/.gitignore b/rzk-playground/rzk-lezer/.gitignore
new file mode 100644
index 000000000..558f07dc9
--- /dev/null
+++ b/rzk-playground/rzk-lezer/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+src/parser*
+examples/tree
\ No newline at end of file
diff --git a/rzk-playground/rzk-lezer/examples/src/example.rzk b/rzk-playground/rzk-lezer/examples/src/example.rzk
new file mode 100644
index 000000000..80b3ddb9f
--- /dev/null
+++ b/rzk-playground/rzk-lezer/examples/src/example.rzk
@@ -0,0 +1,141 @@
+#lang rzk-1
+
+-- A is contractible there exists x : A such that for any y : A we have x = y.
+#def iscontr (A : U) : U
+  := βˆ‘ (a : A), (x : A) -> a =_{A} x
+
+-- A is a proposition if for any x, y : A we have x = y
+#def isaprop (A : U) : U
+  := (x : A) -> (y : A) -> x =_{A} y
+
+-- A is a set if for any x, y : A the type x =_{A} y is a proposition
+#def isaset (A : U) : U
+  := (x : A) -> (y : A) -> isaprop (x =_{A} y)
+
+-- Non-dependent product of A and B
+#def prod (A : U) (B : U) : U
+  := βˆ‘ (x : A), B
+
+-- A function f : A -> B is an equivalence
+-- if there exists g : B -> A
+-- such that for all x : A we have g (f x) = x
+-- and for all y : B we have f (g y) = y
+#def isweq (A : U) (B : U) (f : A -> B) : U
+  := βˆ‘ (g : B -> A), prod ((x : A) -> g (f x) =_{A} x) ((y : B) -> f (g y) =_{B} y)
+
+-- Equivalence of types A and B
+#def weq (A : U) (B : U) : U
+  := βˆ‘ (f : A -> B), isweq A B f
+
+-- Transport along a path
+#def transport
+    (A : U)
+    (C : A -> U)
+    (x y : A)
+    (p : x =_{A} y)
+    : C x -> C y
+  := \cx -> idJ(A, x, (\z q -> C z), cx, y, p)
+
+-- [RS17, Axiom 4.6] Relative function extensionality.
+#def relfunext : U
+  := (I : CUBE)
+  -> (psi : I -> TOPE)
+  -> (phi : psi -> TOPE)
+  -> (A : psi -> U)
+  -> ((t : psi) -> iscontr (A t))
+  -> (a : (t : phi) -> A t)
+  -> (t : psi) -> A t [ phi t |-> a t]
+
+-- [RS17, Proposition 4.8] A (weaker) formulation of function extensionality.
+#def relfunext2 : U
+  := (I : CUBE)
+  -> (psi : I -> TOPE)
+  -> (phi : psi -> TOPE)
+  -> (A : psi -> U)
+  -> (a : (t : phi) -> A t)
+  -> (f : (t : psi) -> A t [ phi t |-> a t ])
+  -> (g : (t : psi) -> A t [ phi t |-> a t ])
+  -> weq (f = g)
+         ((t : psi) -> (f t =_{A t} g t) [ phi t |-> refl ])
+
+-- Restrict extension type to a subshape.
+#def restrict
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \/ phi t} -> U)
+    (a : {t : I | psi t} -> A t)
+  : {t : I | psi t /\ phi t} -> A t
+  := \t -> a t
+
+-- Reformulate extension type as an extension of a restriction.
+#def ext-of-restrict
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \/ phi t} -> U)
+    (a : {t : I | psi t} -> A t)
+  : (t : psi) -> A t [ psi t /\ phi t |-> restrict I psi phi A a t ]
+  := a
+
+-- Transform extension of an identity into an identity of restrictions.
+#def restricts-path
+    (r : relfunext2)
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \/ phi t} -> U)
+    (a_psi : (t : psi) -> A t)
+    (a_phi : (t : phi) -> A t)
+    (e : {t : I | psi t /\ phi t} -> a_psi t = a_phi t)
+  : restrict I psi phi A a_psi = restrict I phi psi A a_phi
+  := (first (second (r I
+      (\t -> psi t /\ phi t)
+      (\t -> BOT)
+      (\t -> A t)
+      (\t -> recBOT)
+      (\t -> a_psi t)
+      (\t -> a_phi t)))) e
+
+-- A weaker version of recOR, demanding only a path between a and b:
+-- recOR(psi, phi, a, b) demands that for psi /\ phi we have a == b (definitionally)
+-- (recId psi phi a b e) demands that e is the proof that a = b (intensionally) for psi /\ phi
+#def recId
+    (r : relfunext2)
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \/ phi t} -> U)
+    (a_psi : (t : psi) -> A t)
+    (a_phi : (t : phi) -> A t)
+    (e : {t : I | psi t /\ phi t} -> a_psi t = a_phi t)
+  : {t : I | psi t \/ phi t} -> A t
+  := \t -> recOR(
+        psi t |-> transport
+          ({t : I | psi t /\ phi t} -> A t)
+          (\ra -> (t : psi) -> A t [ psi t /\ phi t |-> ra t])
+          (restrict I psi phi A a_psi)
+          (restrict I phi psi A a_phi)
+          (restricts-path r I psi phi A a_psi a_phi e)
+          (ext-of-restrict I psi phi A a_psi)
+          t,
+        phi t |-> ext-of-restrict I phi psi A a_phi t
+      )
+
+-- If two extension types are equal along two subshapes,
+-- then they are also equal along their union.
+#def id-along-border
+    (r : relfunext2)
+    (I : CUBE)
+    (psi : I -> TOPE)
+    (phi : I -> TOPE)
+    (A : {t : I | psi t \/ phi t} -> U)
+    (a b : {t : I | psi t \/ phi t} -> A t)
+    (e_psi : (t : psi) -> a t = b t)
+    (e_phi : (t : phi) -> a t = b t)
+    (border-is-a-set : {t : I | psi t /\ phi t} -> isaset (A t))
+  : {t : I | psi t \/ phi t} -> a t = b t
+  := recId r I psi phi
+        (\t -> a t = b t)
+        e_psi e_phi
+        (\t -> border-is-a-set t (a t) (b t) (e_psi t) (e_phi t))
\ No newline at end of file
diff --git a/rzk-playground/rzk-lezer/package-lock.json b/rzk-playground/rzk-lezer/package-lock.json
new file mode 100644
index 000000000..a6b15a062
--- /dev/null
+++ b/rzk-playground/rzk-lezer/package-lock.json
@@ -0,0 +1,529 @@
+{
+  "name": "rzk-lezer",
+  "version": "0.1.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "rzk-lezer",
+      "version": "0.1.0",
+      "dependencies": {
+        "@lezer/lr": "^1.3.12"
+      },
+      "devDependencies": {
+        "@lezer-unofficial/printer": "^1.0.1",
+        "@lezer/generator": "deemp/generator#cc38c10ab0d9d6e9b0e6daf1659e7a15dad86649",
+        "tsx": "^3.13.0"
+      }
+    },
+    "node_modules/@codemirror/state": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz",
+      "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==",
+      "dev": true
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
+      "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
+      "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
+      "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
+      "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
+      "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
+      "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
+      "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
+      "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
+      "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
+      "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
+      "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
+      "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
+      "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
+      "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
+      "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
+      "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
+      "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
+      "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
+      "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
+      "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
+      "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
+      "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@lezer-unofficial/printer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@lezer-unofficial/printer/-/printer-1.0.1.tgz",
+      "integrity": "sha512-0bIixSdtdCyErXna3eKArYFsGfsUiXrgdu7t4gV8mL+2ooVDQArz66py1lSaEpfYI6n2nO11uNyHHvXojUWakw==",
+      "dev": true,
+      "dependencies": {
+        "@codemirror/state": "^6.2.1",
+        "@lezer/common": "^1.1.0"
+      }
+    },
+    "node_modules/@lezer/common": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.0.tgz",
+      "integrity": "sha512-XPIN3cYDXsoJI/oDWoR2tD++juVrhgIago9xyKhZ7IhGlzdDM9QgC8D8saKNCz5pindGcznFr2HBSsEQSWnSjw=="
+    },
+    "node_modules/@lezer/generator": {
+      "version": "1.5.1",
+      "resolved": "git+ssh://git@github.com/deemp/generator.git#cc38c10ab0d9d6e9b0e6daf1659e7a15dad86649",
+      "integrity": "sha512-r2wTPQgpGKFSMyRo7hAa8PaSg3XVcmkX7PCnSWlXoK4d3Y6ZHTNbLD1cdczmrO1D+fLPMimtIcjgYiXQKnVRHQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@lezer/common": "^1.1.0",
+        "@lezer/lr": "^1.3.0"
+      },
+      "bin": {
+        "lezer-generator": "src/lezer-generator.cjs"
+      }
+    },
+    "node_modules/@lezer/lr": {
+      "version": "1.3.12",
+      "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.12.tgz",
+      "integrity": "sha512-5nwY1JzCueUdRtlMBnlf1SUi69iGCq2ABq7WQFQMkn/kxPvoACAEnTp4P17CtXxYr7WCwtYPLL2AEvxKPuF1OQ==",
+      "dependencies": {
+        "@lezer/common": "^1.0.0"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "dev": true
+    },
+    "node_modules/esbuild": {
+      "version": "0.18.20",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
+      "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/android-arm": "0.18.20",
+        "@esbuild/android-arm64": "0.18.20",
+        "@esbuild/android-x64": "0.18.20",
+        "@esbuild/darwin-arm64": "0.18.20",
+        "@esbuild/darwin-x64": "0.18.20",
+        "@esbuild/freebsd-arm64": "0.18.20",
+        "@esbuild/freebsd-x64": "0.18.20",
+        "@esbuild/linux-arm": "0.18.20",
+        "@esbuild/linux-arm64": "0.18.20",
+        "@esbuild/linux-ia32": "0.18.20",
+        "@esbuild/linux-loong64": "0.18.20",
+        "@esbuild/linux-mips64el": "0.18.20",
+        "@esbuild/linux-ppc64": "0.18.20",
+        "@esbuild/linux-riscv64": "0.18.20",
+        "@esbuild/linux-s390x": "0.18.20",
+        "@esbuild/linux-x64": "0.18.20",
+        "@esbuild/netbsd-x64": "0.18.20",
+        "@esbuild/openbsd-x64": "0.18.20",
+        "@esbuild/sunos-x64": "0.18.20",
+        "@esbuild/win32-arm64": "0.18.20",
+        "@esbuild/win32-ia32": "0.18.20",
+        "@esbuild/win32-x64": "0.18.20"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/get-tsconfig": {
+      "version": "4.7.2",
+      "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz",
+      "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==",
+      "dev": true,
+      "dependencies": {
+        "resolve-pkg-maps": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+      }
+    },
+    "node_modules/resolve-pkg-maps": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+      "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dev": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/tsx": {
+      "version": "3.13.0",
+      "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.13.0.tgz",
+      "integrity": "sha512-rjmRpTu3as/5fjNq/kOkOtihgLxuIz6pbKdj9xwP4J5jOLkBxw/rjN5ANw+KyrrOXV5uB7HC8+SrrSJxT65y+A==",
+      "dev": true,
+      "dependencies": {
+        "esbuild": "~0.18.20",
+        "get-tsconfig": "^4.7.2",
+        "source-map-support": "^0.5.21"
+      },
+      "bin": {
+        "tsx": "dist/cli.mjs"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      }
+    }
+  }
+}
diff --git a/rzk-playground/rzk-lezer/package.json b/rzk-playground/rzk-lezer/package.json
new file mode 100644
index 000000000..d28d592a5
--- /dev/null
+++ b/rzk-playground/rzk-lezer/package.json
@@ -0,0 +1,23 @@
+{
+  "name": "rzk-lezer",
+  "version": "0.1.0",
+  "type": "module",
+  "module": "dist/index.js",
+  "devDependencies": {
+    "@lezer/generator": "deemp/generator#cc38c10ab0d9d6e9b0e6daf1659e7a15dad86649",
+    "@lezer-unofficial/printer": "^1.0.1",
+    "tsx": "^3.13.0"
+  },
+  "dependencies": {
+    "@lezer/lr": "^1.3.12"
+  },
+  "files": [
+    "examples"
+  ],
+  "scripts": {
+    "prepare": "npm run build; npm run tsc",
+    "build": "lezer-generator src/rzk.grammar -o src/parser.ts --typeScript",
+    "examples": "tsx src/run-examples.ts",
+    "tsc": "tsc -p tsconfig.json"
+  }
+}
diff --git a/rzk-playground/rzk-lezer/src/run-examples.ts b/rzk-playground/rzk-lezer/src/run-examples.ts
new file mode 100644
index 000000000..a8cfd62b2
--- /dev/null
+++ b/rzk-playground/rzk-lezer/src/run-examples.ts
@@ -0,0 +1,14 @@
+import { parser } from "./parser"
+import { printTree } from "@lezer-unofficial/printer"
+import { readFileSync, readdirSync, writeFileSync, mkdirSync, existsSync } from "fs"
+
+const src = "examples/src"
+const exampleNames = readdirSync(src)
+
+const tree = "examples/tree"
+if (!existsSync(tree)) mkdirSync(tree, { recursive: true })
+
+exampleNames.map(name => {
+  const doc = readFileSync(`${src}/${name}`).toString()
+  writeFileSync(`${tree}/${name}`, printTree(parser.parse(doc), doc))
+})
\ No newline at end of file
diff --git a/rzk-playground/rzk-lezer/src/rzk.grammar b/rzk-playground/rzk-lezer/src/rzk.grammar
new file mode 100644
index 000000000..741139146
--- /dev/null
+++ b/rzk-playground/rzk-lezer/src/rzk.grammar
@@ -0,0 +1,336 @@
+// Other parsers
+// https://github.com/mdaines/viz-js/blob/54ebb476d2d0fb4a3d1f1b6bd77162876c6b6697/packages/lang-dot/src/dot.grammar#L97
+
+@top Program {
+    module
+}
+
+@tokens {
+    varIdentTokenFirst { ![-?!.\\;,#\"\]\[)(}{><| \t\n\r:/*=×→≑↦] }
+    varIdenTokenNext { ![\\;,#\"\]\[)(}{><| \t\n\r] }
+    varIdentToken {  varIdentTokenFirst varIdenTokenNext* }
+        
+    LineComment { "--" ![\n]* }
+    BlockComment { "{-" blockCommentRest }
+    blockCommentRest { ![-] blockCommentRest | "-" blockCommentAfterDash }
+    blockCommentAfterDash { "}" | "-" blockCommentAfterDash | ![{-] blockCommentRest }
+    
+    String { '"' (![\\"] | "\\" _)* '"' }
+    string { String }
+
+    space { $[ \t\r\n]+ }
+
+    "-" "->" "," ":" ":=" "?" "(" ")" "[" "]"
+    "{" "}" "*_1" "*" "*₁" "/\\" "\\" "\\/"
+    "#assume" "#check" "#compute-nf" "#compute-whnf" "#compute" "#def"
+    "#define" "#end" "#lang" "#postulate" "#section" "#set-option"
+    "#unset-option" "#variable" "#variables" 
+    "β†’" "↦" "βˆ‘" "Γ—" "<" "<=" "=_{" "=" "===" ">" "|->" "|" "∧"
+    "∨" "≑" "≀" "⊀" "βŠ₯" "0_2" "0β‚‚" "1_2" "1" "1β‚‚" "2" "as" "BOT" "Cube"
+    "first" "idJ" "recBot" "recOR" "refl_{" "refl" "rzk-1" "second" 
+    "Sigma" "TOP" "TOPE" "U" "unit" "Unit" "uses" "π₁" "Ο€β‚‚" "Ξ£"
+}
+
+@skip { space | LineComment | BlockComment }
+
+Module { languageDecl command*  }
+module { Module }
+
+HoleIdent { "?" }
+holeIdent { HoleIdent }
+
+VarIdent { varIdentToken }
+varIdent { VarIdent }
+varIdents { varIdent+ }
+
+LanguageDecl { "#lang" language }
+languageDecl { LanguageDecl }
+
+Rzk1 { "rzk-1" }
+language { Rzk1 }
+
+CommandSetOption { "#set-option" string "=" string }
+CommandUnsetOption { "#unset-option" string "=" string }
+
+CommandCheck { "#check" term ":" term }
+
+CommandCompute { "#compute" term }
+CommandComputeWHNF { "#compute-whnf" term }
+CommandComputeNF { "#compute-nf" term }
+
+CommandPostulate { "#postulate" varIdent declUsedVars params ":" term }
+CommandPostulateNoParams { "#postulate" varIdent declUsedVars ":" term }
+
+CommandAssume {
+      "#assume" varIdents ":" term
+    | commandVariable
+    | commandVariables
+}
+// TODO Is this equivalent to `define`d functions?
+commandVariable { "#variable" varIdent ":" term }
+commandVariables { "#variables" varIdents ":" term }
+
+CommandSection { "#section" sectionName }
+CommandSectionEnd { "#end" sectionName }
+
+CommandDefine {
+    "#define" varIdent declUsedVars params ":" term ":=" term 
+    | commandDefineNoParams
+    | commandDef
+    | commandDefNoParams
+}
+commandDefineNoParams { "#define" varIdent declUsedVars ":" term ":=" term }
+commandDef { "#def" varIdent declUsedVars params ":" term ":=" term }
+commandDefNoParams { "#def" varIdent declUsedVars ":" term ":=" term }
+
+command {
+    ( CommandSetOption
+    | CommandUnsetOption
+    | CommandCheck
+    | CommandCompute
+    | CommandComputeWHNF
+    | CommandComputeNF
+    | CommandPostulate
+    | CommandPostulateNoParams
+    | CommandAssume
+    | CommandSection
+    | CommandSectionEnd
+    | CommandDefine
+    )
+}
+
+DeclUsedVars { 
+      @specialize<varIdentToken, "uses"> "(" varIdents ")" 
+    | noDeclUsedVars 
+}
+noDeclUsedVars { "" }
+declUsedVars { DeclUsedVars }
+
+NoSectionName  { "" }
+SomeSectionName { varIdent }
+sectionName { 
+      NoSectionName 
+    | SomeSectionName }
+
+// Patterns
+PatternUnit { @specialize<varIdentToken, "unit"> }
+PatternVar { varIdent }
+PatternPair { "(" pattern "," pattern ")" }
+pattern {
+      PatternUnit
+    | PatternVar
+    | PatternPair
+}
+// TODO why separator for nonempty is ""?
+// we can have `unitunit` in `ParamPatternType`
+patterns { pattern+ }
+
+// Parameter introduction (for lambda abstractions)
+ParamPattern { pattern }
+ParamPatternType { "(" patterns ":" term ")" }
+ParamPatternShape { "(" patterns ":" term "|" term ")" }
+ParamPatternShapeDeprecated { "{" pattern ":" term "|" term "}" }
+
+param {
+      ParamPattern
+    | ParamPatternType
+    | ParamPatternShape
+    | ParamPatternShapeDeprecated
+}
+// TODO why ""?
+params { param+ }
+
+// Parameter declaration for functions and extension types
+ParamType { term6 }
+ParamTermType { "(" term ":" term ")" }
+ParamTermShape { "(" term ":" term "|" term ")" }
+ParamTermTypeDeprecated { "{" pattern ":" term "}" } 
+ParamVarShapeDeprecated { "{" "(" pattern ":" term ")" "|" term "}" }
+paramVarShapeDeprecated { "{" pattern ":" term "|" term "}" }
+
+paramDecl {
+      ParamType
+    | ParamTermType
+    | ParamTermShape
+    | ParamTermTypeDeprecated
+    | ParamVarShapeDeprecated
+    | paramVarShapeDeprecated
+}
+
+
+Restriction { term "↦" term }
+restriction { Restriction | ASCII_Restriction }
+
+// TODO use this when see [Restriction]
+restrictions { restriction ("," restriction)* }
+
+// Universes
+Universe { @specialize<varIdentToken, "U"> }
+UniverseCube { @specialize<varIdentToken, "Cube"> }
+UniverseTope { @specialize<varIdentToken, "TOPE"> }
+
+// Cubes
+CubeUnit { @specialize<varIdentToken, "1"> }
+CubeUnitStar { @specialize<varIdentToken, "*₁"> }
+Cube2 { @specialize<varIdentToken, "2"> }
+Cube2_0 { @specialize<varIdentToken, "0β‚‚"> }
+Cube2_1 { @specialize<varIdentToken, "1β‚‚"> }
+CubeProduct { term5 "Γ—" term6 }
+
+// Topes
+TopeTop { @specialize<varIdentToken, "⊀"> }
+TopeBottom { @specialize<varIdentToken, "βŠ₯"> }
+TopeEQ { term5 "≑" term5 }
+TopeLEQ { @specialize<varIdentToken, "≀"> }
+TopeAnd { @specialize<varIdentToken, "∧"> }
+TopeOr { @specialize<varIdentToken, "∨"> }
+
+// Tope disjunction elimination
+RecBottom { @specialize<varIdentToken, "recBot"> }
+RecOr { @specialize<varIdentToken, "recOR"> "(" restrictions ")" }
+RecOrDeprecated { @specialize<varIdentToken, "recOR"> "(" term "," term "," term "," term ")" }
+
+// Types
+TypeFun { paramDecl "β†’" term1 }
+TypeSigma { @specialize<varIdentToken, "Ξ£"> "(" pattern ":" term ")" "," term1 }
+TypeUnit { @specialize<varIdentToken, "Unit"> }
+TypeId { term2 "=_{" term "}" term2 }
+TypeIdSimple { term2 "=" term2 }
+TypeRestricted { term6 "[" restrictions "]" }
+TypeExtensionDeprecated { "<" paramDecl "β†’" term ">" }
+
+// Terms
+App { term6 term7  }
+Lambda { "\\" params "β†’" term1  }
+Pair { "(" term "," term ")"  }
+First { @specialize<varIdentToken, "π₁"> term7  }
+Second { @specialize<varIdentToken, "Ο€β‚‚"> term7  }
+// FIXME same as PatternUnit
+Unit { @specialize<varIdentToken, "unit">  }
+Refl { @specialize<varIdentToken, "refl"> }
+ReflTerm { @specialize<varIdentToken, "refl_{"> term "}"  }
+ReflTermType { @specialize<varIdentToken, "refl_{"> term ":" term "}"  }
+IdJ { @specialize<varIdentToken, "idJ"> "(" term "," term "," term "," term "," term "," term ")"  }
+
+// Variables and holes
+Hole { holeIdent }
+Var { varIdent }
+
+// Miscellaneous
+TypeAsc { term2 @specialize<varIdentToken, "as"> term1 }
+
+ascii_CubeProduct { term5 @specialize<varIdentToken, "*"> term6 }
+
+ASCII_CubeUnitStar { @specialize<varIdentToken, "*_1"> }
+ASCII_Cube2_0 { @specialize<varIdentToken, "0_2"> }
+ASCII_Cube2_1 { @specialize<varIdentToken, "1_2"> }
+
+ASCII_TopeTop { @specialize<varIdentToken, "TOP"> }
+ASCII_TopeBottom { @specialize<varIdentToken, "BOT"> }
+ASCII_TopeEQ { term5 "===" term5 }
+ASCII_TopeLEQ { term5 "<=" term5 }
+ASCII_TopeAnd { term4 "/\\" term3 }
+ASCII_TopeOr { term3 "\\/" term2 }
+ 
+ASCII_TypeFun { paramDecl "->" term1 }
+ASCII_TypeSigma { @specialize<varIdentToken, "Sigma"> "(" pattern ":" term ")" "," term1 }
+
+ASCII_Lambda { "\\" params "->" term1 }
+ASCII_Restriction { term "|->" term }
+
+ASCII_TypeExtensionDeprecated { "<" paramDecl "->" term ">" }
+ASCII_First { @specialize<varIdentToken, "first"> term7 }
+ASCII_Second { @specialize<varIdentToken, "second"> term7 }
+
+// Alternative Unicode syntax rules
+// \sum
+unicode_TypeSigmaAlt { @specialize<varIdentToken, "βˆ‘"> "(" pattern ":" term ")" "," term1 }
+
+// coercions *add* rules
+
+term { 
+  TypeAsc
+| term1 
+}
+
+term1 {
+      TypeFun
+    | TypeSigma
+    | TypeId
+    | TypeIdSimple
+    | Lambda
+    | ASCII_TypeFun
+    | ASCII_TypeSigma
+    | ASCII_Lambda
+    | unicode_TypeSigmaAlt
+    | term2
+}
+
+term2 {
+      TopeOr
+    | ASCII_TopeOr
+    | term3
+}
+
+term3 {
+      TopeAnd
+    | ASCII_TopeAnd
+    | term4
+}
+
+term4 {
+      TopeEQ
+    | TopeLEQ
+    | ASCII_TopeEQ
+    | ASCII_TopeLEQ
+    | term5
+}
+
+term5 {
+      CubeProduct
+    | ascii_CubeProduct
+    | term6
+}
+
+term6 {
+      TypeRestricted
+    | App
+    | First
+    | Second
+    | ASCII_First
+    | ASCII_Second
+    | term7
+}
+
+term7 {
+      Universe
+    | UniverseCube
+    | UniverseTope
+    | CubeUnit
+    | CubeUnitStar
+    | Cube2
+    | Cube2_0
+    | Cube2_1
+    | TopeTop
+    | TopeBottom
+    | RecBottom
+    | RecOr
+    | RecOrDeprecated
+    | TypeUnit
+    | TypeExtensionDeprecated
+    | Pair
+    | Unit
+    | Refl
+    | ReflTerm
+    | ReflTermType
+    | IdJ
+    | Hole
+    | Var
+    | ASCII_CubeUnitStar
+    | ASCII_Cube2_0
+    | ASCII_Cube2_1
+    | ASCII_TopeTop
+    | ASCII_TopeBottom
+    | ASCII_TypeExtensionDeprecated
+    | "(" term ")"
+}
diff --git a/rzk-playground/rzk-lezer/tsconfig.json b/rzk-playground/rzk-lezer/tsconfig.json
new file mode 100644
index 000000000..c8898f48a
--- /dev/null
+++ b/rzk-playground/rzk-lezer/tsconfig.json
@@ -0,0 +1,21 @@
+{
+    "compilerOptions": {
+        "lib": [
+            "ESNext"
+        ],
+        "noImplicitReturns": true,
+        "noUnusedLocals": true,
+        "strict": true,
+        "target": "ESNext",
+        "module": "ESNext",
+        "newLine": "lf",
+        "preserveConstEnums": true,
+        "stripInternal": true,
+        "moduleResolution": "node",
+        "outDir": "dist",
+        "declaration": true
+    },
+    "include": [
+        "src"
+    ]
+}
\ No newline at end of file
diff --git a/rzk-playground/src/rzk-wrapper.js b/rzk-playground/src/rzk-wrapper.js
new file mode 100644
index 000000000..f0e692711
--- /dev/null
+++ b/rzk-playground/src/rzk-wrapper.js
@@ -0,0 +1,5 @@
+export function rzkTypecheck(input) {
+    var tmp = { input }
+    rzkTypecheck_(tmp)
+    return tmp
+}
\ No newline at end of file
diff --git a/rzk-playground/src/rzk.ts b/rzk-playground/src/rzk.ts
new file mode 100644
index 000000000..809afc6da
--- /dev/null
+++ b/rzk-playground/src/rzk.ts
@@ -0,0 +1,8 @@
+import * as wrapper from "./rzk-wrapper"
+
+export type Result = { status: string, result: string }
+
+export function typecheck(input: string) {
+    let result: Result = wrapper.rzkTypecheck(input) as any
+    return result
+}
\ No newline at end of file
diff --git a/rzk-playground/tsconfig.json b/rzk-playground/tsconfig.json
new file mode 100644
index 000000000..e59724b28
--- /dev/null
+++ b/rzk-playground/tsconfig.json
@@ -0,0 +1,27 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "lib": ["dom", "dom.iterable", "esnext"],
+    "allowJs": true,
+    "skipLibCheck": true,
+    "strict": true,
+    "noEmit": true,
+    "esModuleInterop": true,
+    "module": "esnext",
+    "moduleResolution": "bundler",
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "jsx": "preserve",
+    "incremental": true,
+    "plugins": [
+      {
+        "name": "next"
+      }
+    ],
+    "paths": {
+      "@/*": ["./src/*"]
+    }
+  },
+  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+  "exclude": ["node_modules"]
+}
diff --git a/rzk/ChangeLog.md b/rzk/ChangeLog.md
index eebeeb85f..4bbfc6fe2 100644
--- a/rzk/ChangeLog.md
+++ b/rzk/ChangeLog.md
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to the
 [Haskell Package Versioning Policy](https://pvp.haskell.org/).
 
+## v0.6.5 β€” 2023-10-01
+
+This version contains mostly intrastructure improvements:
+
+- Typecheck using `rzk.yaml` if it exists (see [#119](https://github.com/rzk-lang/rzk/pull/119))
+- Update Rzk Playground and Nix Flake (see [#84](https://github.com/rzk-lang/rzk/pull/84))
+  - Rzk Playground now uses CodeMirror 6 and NextJS
+  - `miso` dependency is dropped
+  - GHCJS 9.6 is now used
+  - Support `snippet={code}` or `code={code}` param (see [#118](https://github.com/rzk-lang/rzk/pull/118))
+    - Support for `snippet_url={URL}` is temporarily dropped
+- Update to GHC 9.6, latest Stackage Nightly, improve Rzk setup, and GitHub Actions (see [#116](https://github.com/rzk-lang/rzk/pull/116))
+- Add logging for Rzk Language Server (see [#114](https://github.com/rzk-lang/rzk/pull/114))
+
+Fixes:
+
+- Fix error messages in Rzk Playground (see [#115](https://github.com/rzk-lang/rzk/pull/115))
+
 ## v0.6.4 β€” 2023-09-27
 
 This version improves the stucture of the project, in particular w.r.t dependencies:
diff --git a/rzk/Setup.hs b/rzk/Setup.hs
index 9a994af67..9f58444e6 100644
--- a/rzk/Setup.hs
+++ b/rzk/Setup.hs
@@ -1,2 +1,29 @@
-import Distribution.Simple
-main = defaultMain
+-- Source: https://github.com/haskell/cabal/issues/6726#issuecomment-918663262
+
+-- | Custom Setup that runs bnfc to generate the language sub-libraries
+-- for the parsers included in Ogma.
+module Main (main) where
+
+import           Distribution.Simple         (defaultMainWithHooks,
+                                              hookedPrograms, postConf,
+                                              preBuild, simpleUserHooks)
+import           Distribution.Simple.Program (Program (..), findProgramVersion,
+                                              simpleProgram)
+import           System.Process              (system)
+
+-- | Run BNFC on the grammar before the actual build step.
+--
+-- All options for bnfc are hard-coded here.
+main :: IO ()
+main = defaultMainWithHooks $ simpleUserHooks
+  { hookedPrograms = [ bnfcProgram ]
+  , postConf       = \args flags packageDesc localBuildInfo -> do
+      _ <- system "bnfc -d -p Language.Rzk --generic --functor -o src/ grammar/Syntax.cf"
+      postConf simpleUserHooks args flags packageDesc localBuildInfo
+  }
+
+-- | TODO: This should be in Cabal.Distribution.Simple.Program.Builtin.
+bnfcProgram :: Program
+bnfcProgram = (simpleProgram "bnfc")
+  { programFindVersion = findProgramVersion "--version" id
+  }
diff --git a/rzk/src/Language/Rzk/Syntax.cf b/rzk/grammar/Syntax.cf
similarity index 99%
rename from rzk/src/Language/Rzk/Syntax.cf
rename to rzk/grammar/Syntax.cf
index b1a558c3a..2c3ce32f6 100644
--- a/rzk/src/Language/Rzk/Syntax.cf
+++ b/rzk/grammar/Syntax.cf
@@ -73,7 +73,7 @@ separator nonempty Param "" ;
 ParamType.          ParamDecl ::= Term6 ;
 ParamTermType.      ParamDecl ::= "(" Term ":" Term ")" ;
 ParamTermShape.     ParamDecl ::= "(" Term ":" Term "|" Term ")" ;
-ParamTermTypeDeprecated. ParamDecl ::= "{" Pattern ":" Term "}" ; 
+ParamTermTypeDeprecated. ParamDecl ::= "{" Pattern ":" Term "}" ;
 ParamVarShapeDeprecated. ParamDecl ::= "{" "(" Pattern ":" Term ")" "|" Term "}" ;
 paramVarShapeDeprecated. ParamDecl ::= "{" Pattern ":" Term "|" Term "}" ;
 define paramVarShapeDeprecated pat cube tope = ParamVarShapeDeprecated pat cube tope ;
@@ -161,4 +161,4 @@ ASCII_Second.         Term6 ::= "second" Term7 ;
 -- Alternative Unicode syntax rules
 
 unicode_TypeSigmaAlt.   Term1 ::= "βˆ‘" "(" Pattern ":" Term ")" "," Term1 ;    -- \sum
-define unicode_TypeSigmaAlt pat fst snd = TypeSigma pat fst snd ;
\ No newline at end of file
+define unicode_TypeSigmaAlt pat fst snd = TypeSigma pat fst snd ;
diff --git a/rzk/package.yaml b/rzk/package.yaml
index aee198888..18f4125b7 100644
--- a/rzk/package.yaml
+++ b/rzk/package.yaml
@@ -1,5 +1,5 @@
 name: rzk
-version: 0.6.4
+version: 0.6.5
 github: 'rzk-lang/rzk'
 license: BSD3
 author: 'Nikolai Kudasov'
@@ -9,6 +9,7 @@ copyright: '2023 Nikolai Kudasov'
 extra-source-files:
   - README.md
   - ChangeLog.md
+  - grammar/Syntax.cf
 
 synopsis: An experimental proof assistant for synthetic ∞-categories
 category: Dependent Types # same as Agda
@@ -21,30 +22,33 @@ description: Please see the README on GitHub at <https://github.com/rzk-lang/rzk
 flags:
   lsp:
     description: >-
-      Build with LSP support.
+      Build with LSP support (only available with GHC, not GHCJS).
     manual: true
     default: true
 
+custom-setup:
+  dependencies:
+    base:    ">= 4.11.0.0 && < 5.0"
+    Cabal:   ">= 2.4.0.1 && < 4.0"
+    process: ">= 1.6.3.0"
+
 build-tools:
   alex:   ">= 3.2.4"
   happy:  ">= 1.19.9"
+  BNFC:   ">= 2.9.4.1"
 
 dependencies:
   array: ">= 0.5.3.0"
-  aeson: ">= 1.4.2.0"
   base: ">= 4.7 && < 5"
   bifunctors: ">= 5.5.3"
   bytestring: ">= 0.10.8.2"
+  directory: ">= 1.2.7.0"
+  Glob: ">= 0.9.3"
   mtl: ">= 2.2.2"
+  optparse-generic: ">= 1.3.0"
   template-haskell: ">= 2.14.0.0"
   text: ">= 1.2.3.1"
-  optparse-generic: ">= 1.3.0"
-  Glob: ">= 0.9.3"
-  lens: ">= 4.17"
-  filepath: ">= 1.4.2.1"
-  stm: ">= 2.5.0.0"
   yaml: ">= 0.11.0.0"
-  data-default-class: ">= 0.1.2.0"
 
 ghc-options:
   - -Wall
@@ -70,11 +74,18 @@ library:
         - Language.Rzk.VSCode.Env
         - Language.Rzk.VSCode.Handlers
         - Language.Rzk.VSCode.Lsp
-        - Language.Rzk.VSCode.State
         - Language.Rzk.VSCode.Tokenize
+        - Language.Rzk.VSCode.Logging
       dependencies:
-        lsp: ">= 2.1.0.0"
-        lsp-types: ">= 2.0.1.0"
+        aeson: ">= 1.4.2.0"
+        co-log-core: ">= 0.3.2.0"
+        data-default-class: ">= 0.1.2.0"
+        filepath: ">= 1.4.2.1"
+        lens: ">= 4.17"
+        lsp: ">= 2.2.0.0"
+        lsp-types: ">= 2.0.2.0"
+        stm: ">= 2.5.0.0"
+      cpp-options: -DLSP
 
 executables:
   rzk:
@@ -87,7 +98,7 @@ executables:
     dependencies:
       - rzk
     when:
-      - condition: flag(lsp) && !impl(ghcjs)
+      - condition: "!impl(ghcjs)"
         dependencies:
           with-utf8: ">= 1.0.2.4"
 
diff --git a/rzk/rzk.cabal b/rzk/rzk.cabal
index 83204f2c4..039ad700a 100644
--- a/rzk/rzk.cabal
+++ b/rzk/rzk.cabal
@@ -1,11 +1,11 @@
-cabal-version: 1.12
+cabal-version: 1.24
 
--- This file has been generated from package.yaml by hpack version 0.35.2.
+-- This file has been generated from package.yaml by hpack version 0.36.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           rzk
-version:        0.6.4
+version:        0.6.5
 synopsis:       An experimental proof assistant for synthetic ∞-categories
 description:    Please see the README on GitHub at <https://github.com/rzk-lang/rzk#readme>
 category:       Dependent Types
@@ -16,17 +16,24 @@ maintainer:     nickolay.kudasov@gmail.com
 copyright:      2023 Nikolai Kudasov
 license:        BSD3
 license-file:   LICENSE
-build-type:     Simple
+build-type:     Custom
 extra-source-files:
     README.md
     ChangeLog.md
+    grammar/Syntax.cf
 
 source-repository head
   type: git
   location: https://github.com/rzk-lang/rzk
 
+custom-setup
+  setup-depends:
+      Cabal >=2.4.0.1 && <4.0
+    , base >=4.11.0.0 && <5.0
+    , process >=1.6.3.0
+
 flag lsp
-  description: Build with LSP support.
+  description: Build with LSP support (only available with GHC, not GHCJS).
   manual: True
   default: True
 
@@ -43,6 +50,7 @@ library
       Language.Rzk.Syntax.Print
       Rzk
       Rzk.Main
+      Rzk.Project.Config
       Rzk.TypeCheck
   other-modules:
       Paths_rzk
@@ -52,19 +60,17 @@ library
   build-tools:
       alex >=3.2.4
     , happy >=1.19.9
+  build-tool-depends:
+      BNFC:BNFC >=2.9.4.1
   build-depends:
       Glob >=0.9.3
-    , aeson >=1.4.2.0
     , array >=0.5.3.0
     , base >=4.7 && <5
     , bifunctors >=5.5.3
     , bytestring >=0.10.8.2
-    , data-default-class >=0.1.2.0
-    , filepath >=1.4.2.1
-    , lens >=4.17
+    , directory >=1.2.7.0
     , mtl >=2.2.2
     , optparse-generic >=1.3.0
-    , stm >=2.5.0.0
     , template-haskell >=2.14.0.0
     , text >=1.2.3.1
     , yaml >=0.11.0.0
@@ -74,11 +80,18 @@ library
         Language.Rzk.VSCode.Env
         Language.Rzk.VSCode.Handlers
         Language.Rzk.VSCode.Lsp
-        Language.Rzk.VSCode.State
         Language.Rzk.VSCode.Tokenize
+        Language.Rzk.VSCode.Logging
+    cpp-options: -DLSP
     build-depends:
-        lsp >=2.1.0.0
-      , lsp-types >=2.0.1.0
+        aeson >=1.4.2.0
+      , co-log-core >=0.3.2.0
+      , data-default-class >=0.1.2.0
+      , filepath >=1.4.2.1
+      , lens >=4.17
+      , lsp >=2.2.0.0
+      , lsp-types >=2.0.2.0
+      , stm >=2.5.0.0
 
 executable rzk
   main-is: Main.hs
@@ -90,25 +103,23 @@ executable rzk
   build-tools:
       alex >=3.2.4
     , happy >=1.19.9
+  build-tool-depends:
+      BNFC:BNFC >=2.9.4.1
   build-depends:
       Glob >=0.9.3
-    , aeson >=1.4.2.0
     , array >=0.5.3.0
     , base >=4.7 && <5
     , bifunctors >=5.5.3
     , bytestring >=0.10.8.2
-    , data-default-class >=0.1.2.0
-    , filepath >=1.4.2.1
-    , lens >=4.17
+    , directory >=1.2.7.0
     , mtl >=2.2.2
     , optparse-generic >=1.3.0
     , rzk
-    , stm >=2.5.0.0
     , template-haskell >=2.14.0.0
     , text >=1.2.3.1
     , yaml >=0.11.0.0
   default-language: Haskell2010
-  if flag(lsp) && !impl(ghcjs)
+  if !impl(ghcjs)
     build-depends:
         with-utf8 >=1.0.2.4
 
@@ -121,21 +132,19 @@ test-suite doctests
   build-tools:
       alex >=3.2.4
     , happy >=1.19.9
+  build-tool-depends:
+      BNFC:BNFC >=2.9.4.1
   build-depends:
       Glob
     , QuickCheck
-    , aeson >=1.4.2.0
     , array >=0.5.3.0
     , base
     , bifunctors >=5.5.3
     , bytestring >=0.10.8.2
-    , data-default-class >=0.1.2.0
+    , directory >=1.2.7.0
     , doctest
-    , filepath >=1.4.2.1
-    , lens >=4.17
     , mtl >=2.2.2
     , optparse-generic >=1.3.0
-    , stm >=2.5.0.0
     , template-haskell
     , text >=1.2.3.1
     , yaml >=0.11.0.0
@@ -152,20 +161,18 @@ test-suite rzk-test
   build-tools:
       alex >=3.2.4
     , happy >=1.19.9
+  build-tool-depends:
+      BNFC:BNFC >=2.9.4.1
   build-depends:
       Glob >=0.9.3
-    , aeson >=1.4.2.0
     , array >=0.5.3.0
     , base >=4.7 && <5
     , bifunctors >=5.5.3
     , bytestring >=0.10.8.2
-    , data-default-class >=0.1.2.0
-    , filepath >=1.4.2.1
-    , lens >=4.17
+    , directory >=1.2.7.0
     , mtl >=2.2.2
     , optparse-generic >=1.3.0
     , rzk
-    , stm >=2.5.0.0
     , template-haskell >=2.14.0.0
     , text >=1.2.3.1
     , yaml >=0.11.0.0
diff --git a/rzk/rzk.nix b/rzk/rzk.nix
deleted file mode 100644
index 08c937a42..000000000
--- a/rzk/rzk.nix
+++ /dev/null
@@ -1,32 +0,0 @@
-{ mkDerivation, aeson, alex, array, base, bifunctors, bytestring
-, data-default-class, doctest, filepath, Glob, happy, hpack, lens
-, lib, mtl, optparse-generic, QuickCheck, stm, template-haskell
-, text, yaml
-}:
-mkDerivation {
-  pname = "rzk";
-  version = "0.6.4";
-  src = ./.;
-  isLibrary = true;
-  isExecutable = true;
-  libraryHaskellDepends = [
-    aeson array base bifunctors bytestring data-default-class filepath
-    Glob lens mtl optparse-generic stm template-haskell text yaml
-  ];
-  libraryToolDepends = [ alex happy hpack ];
-  executableHaskellDepends = [
-    aeson array base bifunctors bytestring data-default-class filepath
-    Glob lens mtl optparse-generic stm template-haskell text yaml
-  ];
-  executableToolDepends = [ alex happy ];
-  testHaskellDepends = [
-    aeson array base bifunctors bytestring data-default-class doctest
-    filepath Glob lens mtl optparse-generic QuickCheck stm
-    template-haskell text yaml
-  ];
-  testToolDepends = [ alex happy ];
-  prePatch = "hpack";
-  homepage = "https://github.com/rzk-lang/rzk#readme";
-  description = "An experimental proof assistant for synthetic ∞-categories";
-  license = lib.licenses.bsd3;
-}
diff --git a/rzk/src/Language/Rzk/Free/Syntax.hs b/rzk/src/Language/Rzk/Free/Syntax.hs
index d9803bcd8..786b17b6b 100644
--- a/rzk/src/Language/Rzk/Free/Syntax.hs
+++ b/rzk/src/Language/Rzk/Free/Syntax.hs
@@ -94,7 +94,7 @@ data TermF scope term
     | TypeUnitF
     | TypeAscF term term
     | TypeRestrictedF term [(term, term)]
-    deriving (Eq)
+    deriving (Eq, Functor, Foldable, Traversable)
 deriveBifunctor ''TermF
 deriveBifoldable ''TermF
 deriveBitraversable ''TermF
diff --git a/rzk/src/Language/Rzk/Syntax.hs b/rzk/src/Language/Rzk/Syntax.hs
index 32d15c0e2..291a883e3 100644
--- a/rzk/src/Language/Rzk/Syntax.hs
+++ b/rzk/src/Language/Rzk/Syntax.hs
@@ -9,7 +9,7 @@ module Language.Rzk.Syntax (
   parseModuleRzk,
   parseModuleFile,
   parseTerm,
-  printTree,
+  Print.Print(..), printTree,
   tryExtractMarkdownCodeBlocks,
   extractMarkdownCodeBlocks,
   tryOrDisplayException,
@@ -23,7 +23,7 @@ import           Data.Char                  (isSpace)
 import qualified Data.List                  as List
 
 import           Language.Rzk.Syntax.Abs
-import           Language.Rzk.Syntax.Print  (printTree)
+import qualified Language.Rzk.Syntax.Print  as Print
 
 import           Language.Rzk.Syntax.Layout (resolveLayout)
 import           Language.Rzk.Syntax.Lex    (tokens)
@@ -121,3 +121,69 @@ identifyCodeBlockStart line
   | otherwise = NonCode
   where
     (prefix, suffix) = List.splitAt 3 line
+
+-- * Overriding BNFC pretty-printer
+
+-- | Like 'Print.printTree', but does not insert newlines for curly braces.
+printTree :: Print.Print a => a -> String
+printTree = render . Print.prt 0
+
+-- | Like 'Print.render', but does not insert newlines for curly braces.
+render :: Print.Doc -> String
+render d = rend 0 False (map ($ "") $ d []) ""
+  where
+  rend
+    :: Int        -- ^ Indentation level.
+    -> Bool       -- ^ Pending indentation to be output before next character?
+    -> [String]
+    -> ShowS
+  rend i p = \case
+      "["      :ts -> char '[' . rend i False ts
+      "("      :ts -> char '(' . rend i False ts
+      -- "{"      :ts -> onNewLine i     p . showChar   '{'  . new (i+1) ts
+      -- "}" : ";":ts -> onNewLine (i-1) p . showString "};" . new (i-1) ts
+      -- "}"      :ts -> onNewLine (i-1) p . showChar   '}'  . new (i-1) ts
+      [";"]        -> char ';'
+      ";"      :ts -> char ';' . new i ts
+      t  : ts@(s:_) | closingOrPunctuation s
+                   -> pending . showString t . rend i False ts
+      t        :ts -> pending . space t      . rend i False ts
+      []           -> id
+    where
+    -- Output character after pending indentation.
+    char :: Char -> ShowS
+    char c = pending . showChar c
+
+    -- Output pending indentation.
+    pending :: ShowS
+    pending = if p then indent i else id
+
+  -- Indentation (spaces) for given indentation level.
+  indent :: Int -> ShowS
+  indent i = Print.replicateS (2*i) (showChar ' ')
+
+  -- Continue rendering in new line with new indentation.
+  new :: Int -> [String] -> ShowS
+  new j ts = showChar '\n' . rend j True ts
+
+  -- -- Make sure we are on a fresh line.
+  -- onNewLine :: Int -> Bool -> ShowS
+  -- onNewLine i p = (if p then id else showChar '\n') . indent i
+
+  -- Separate given string from following text by a space (if needed).
+  space :: String -> ShowS
+  space t s =
+    case (all isSpace t, null spc, null rest) of
+      (True , _   , True ) -> []             -- remove trailing space
+      (False, _   , True ) -> t              -- remove trailing space
+      (False, True, False) -> t ++ ' ' : s   -- add space if none
+      _                    -> t ++ s
+    where
+      (spc, rest) = span isSpace s
+
+  closingOrPunctuation :: String -> Bool
+  closingOrPunctuation [c] = c `elem` closerOrPunct
+  closingOrPunctuation _   = False
+
+  closerOrPunct :: String
+  closerOrPunct = ")],;"
diff --git a/rzk/src/Language/Rzk/Syntax/Abs.hs b/rzk/src/Language/Rzk/Syntax/Abs.hs
index 8db5cb725..ad4c07fbe 100644
--- a/rzk/src/Language/Rzk/Syntax/Abs.hs
+++ b/rzk/src/Language/Rzk/Syntax/Abs.hs
@@ -1,4 +1,4 @@
--- File generated by the BNF Converter (bnfc 2.9.4.1).
+-- File generated by the BNF Converter (bnfc 2.9.5).
 
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric #-}
diff --git a/rzk/src/Language/Rzk/Syntax/Doc.txt b/rzk/src/Language/Rzk/Syntax/Doc.txt
index 23945171e..ea571c2c7 100644
--- a/rzk/src/Language/Rzk/Syntax/Doc.txt
+++ b/rzk/src/Language/Rzk/Syntax/Doc.txt
@@ -183,4 +183,4 @@ All other symbols are terminals.
 
 
 
-%% File generated by the BNF Converter (bnfc 2.9.4.1).
+%% File generated by the BNF Converter (bnfc 2.9.5).
diff --git a/rzk/src/Language/Rzk/Syntax/ErrM.hs b/rzk/src/Language/Rzk/Syntax/ErrM.hs
index af480a444..dfdbb62f2 100644
--- a/rzk/src/Language/Rzk/Syntax/ErrM.hs
+++ b/rzk/src/Language/Rzk/Syntax/ErrM.hs
@@ -1,4 +1,4 @@
--- File generated by the BNF Converter (bnfc 2.9.4.1).
+-- File generated by the BNF Converter (bnfc 2.9.5).
 
 {-# LANGUAGE CPP #-}
 
diff --git a/rzk/src/Language/Rzk/Syntax/Layout.hs b/rzk/src/Language/Rzk/Syntax/Layout.hs
index 535c8ed70..a1b7e9f27 100644
--- a/rzk/src/Language/Rzk/Syntax/Layout.hs
+++ b/rzk/src/Language/Rzk/Syntax/Layout.hs
@@ -1,4 +1,4 @@
--- File generated by the BNF Converter (bnfc 2.9.4.1).
+-- File generated by the BNF Converter (bnfc 2.9.5).
 
 {-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
 
diff --git a/rzk/src/Language/Rzk/Syntax/Lex.x b/rzk/src/Language/Rzk/Syntax/Lex.x
index 3f9269636..b8e8c474b 100644
--- a/rzk/src/Language/Rzk/Syntax/Lex.x
+++ b/rzk/src/Language/Rzk/Syntax/Lex.x
@@ -1,4 +1,4 @@
--- -*- haskell -*- File generated by the BNF Converter (bnfc 2.9.4.1).
+-- -*- haskell -*- File generated by the BNF Converter (bnfc 2.9.5).
 
 -- Lexer definition for use with Alex 3
 {
diff --git a/rzk/src/Language/Rzk/Syntax/Par.y b/rzk/src/Language/Rzk/Syntax/Par.y
index b85611599..f2967f020 100644
--- a/rzk/src/Language/Rzk/Syntax/Par.y
+++ b/rzk/src/Language/Rzk/Syntax/Par.y
@@ -1,4 +1,4 @@
--- -*- haskell -*- File generated by the BNF Converter (bnfc 2.9.4.1).
+-- -*- haskell -*- File generated by the BNF Converter (bnfc 2.9.5).
 
 -- Parser definition for use with Happy
 {
diff --git a/rzk/src/Language/Rzk/Syntax/Print.hs b/rzk/src/Language/Rzk/Syntax/Print.hs
index d6d84fd3a..c31b45a6e 100644
--- a/rzk/src/Language/Rzk/Syntax/Print.hs
+++ b/rzk/src/Language/Rzk/Syntax/Print.hs
@@ -1,8 +1,8 @@
--- File generated by the BNF Converter (bnfc 2.9.4.1).
+-- File generated by the BNF Converter (bnfc 2.9.5).
 
-{-# LANGUAGE CPP                  #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE LambdaCase           #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE LambdaCase #-}
 #if __GLASGOW_HASKELL__ <= 708
 {-# LANGUAGE OverlappingInstances #-}
 #endif
@@ -11,13 +11,16 @@
 
 module Language.Rzk.Syntax.Print where
 
-import           Data.Char               (Char, isSpace)
+import Prelude
+  ( ($), (.)
+  , Bool(..), (==), (<)
+  , Int, Integer, Double, (+), (-), (*)
+  , String, (++)
+  , ShowS, showChar, showString
+  , all, elem, foldr, id, map, null, replicate, shows, span
+  )
+import Data.Char ( Char, isSpace )
 import qualified Language.Rzk.Syntax.Abs
-import           Prelude                 (Bool (..), Double, Int, Integer,
-                                          ShowS, String, all, elem, foldr, id,
-                                          map, null, replicate, showChar,
-                                          showString, shows, span, ($), (*),
-                                          (++), (.), (<), (==))
 
 -- | The top-level printing method.
 
@@ -40,9 +43,9 @@ render d = rend 0 False (map ($ "") $ d []) ""
   rend i p = \case
       "["      :ts -> char '[' . rend i False ts
       "("      :ts -> char '(' . rend i False ts
-      -- "{"      :ts -> onNewLine i     p . showChar   '{'  . new (i+1) ts
-      -- "}" : ";":ts -> onNewLine (i-1) p . showString "};" . new (i-1) ts
-      -- "}"      :ts -> onNewLine (i-1) p . showChar   '}'  . new (i-1) ts
+      "{"      :ts -> onNewLine i     p . showChar   '{'  . new (i+1) ts
+      "}" : ";":ts -> onNewLine (i-1) p . showString "};" . new (i-1) ts
+      "}"      :ts -> onNewLine (i-1) p . showChar   '}'  . new (i-1) ts
       [";"]        -> char ';'
       ";"      :ts -> char ';' . new i ts
       t  : ts@(s:_) | closingOrPunctuation s
@@ -67,19 +70,18 @@ render d = rend 0 False (map ($ "") $ d []) ""
   new j ts = showChar '\n' . rend j True ts
 
   -- Make sure we are on a fresh line.
-  -- onNewLine :: Int -> Bool -> ShowS
-  -- onNewLine i p = (if p then id else showChar '\n') . indent i
+  onNewLine :: Int -> Bool -> ShowS
+  onNewLine i p = (if p then id else showChar '\n') . indent i
 
   -- Separate given string from following text by a space (if needed).
   space :: String -> ShowS
   space t s =
-    case (all isSpace t', null spc, null rest) of
-      (True , _   , True ) -> []              -- remove trailing space
-      (False, _   , True ) -> t'              -- remove trailing space
-      (False, True, False) -> t' ++ ' ' : s   -- add space if none
-      _                    -> t' ++ s
+    case (all isSpace t, null spc, null rest) of
+      (True , _   , True ) -> []             -- remove trailing space
+      (False, _   , True ) -> t              -- remove trailing space
+      (False, True, False) -> t ++ ' ' : s   -- add space if none
+      _                    -> t ++ s
     where
-      t'          = showString t []
       (spc, rest) = span isSpace s
 
   closingOrPunctuation :: String -> Bool
@@ -121,10 +123,10 @@ printString s = doc (showChar '"' . concatS (map (mkEsc '"') s) . showChar '"')
 mkEsc :: Char -> Char -> ShowS
 mkEsc q = \case
   s | s == q -> showChar '\\' . showChar s
-  '\\'       -> showString "\\\\"
-  '\n'       -> showString "\\n"
-  '\t'       -> showString "\\t"
-  s          -> showChar s
+  '\\' -> showString "\\\\"
+  '\n' -> showString "\\n"
+  '\t' -> showString "\\t"
+  s -> showChar s
 
 prPrec :: Int -> Int -> Doc -> Doc
 prPrec i j = if j < i then parenth else id
@@ -152,8 +154,8 @@ instance Print (Language.Rzk.Syntax.Abs.VarIdent' a) where
     Language.Rzk.Syntax.Abs.VarIdent _ varidenttoken -> prPrec i 0 (concatD [prt 0 varidenttoken])
 
 instance Print [Language.Rzk.Syntax.Abs.VarIdent' a] where
-  prt _ []     = concatD []
-  prt _ [x]    = concatD [prt 0 x]
+  prt _ [] = concatD []
+  prt _ [x] = concatD [prt 0 x]
   prt _ (x:xs) = concatD [prt 0 x, prt 0 xs]
 
 instance Print (Language.Rzk.Syntax.Abs.LanguageDecl' a) where
@@ -179,7 +181,7 @@ instance Print (Language.Rzk.Syntax.Abs.Command' a) where
     Language.Rzk.Syntax.Abs.CommandDefine _ varident declusedvars params term1 term2 -> prPrec i 0 (concatD [doc (showString "#define"), prt 0 varident, prt 0 declusedvars, prt 0 params, doc (showString ":"), prt 0 term1, doc (showString ":="), prt 0 term2])
 
 instance Print [Language.Rzk.Syntax.Abs.Command' a] where
-  prt _ []     = concatD []
+  prt _ [] = concatD []
   prt _ (x:xs) = concatD [prt 0 x, doc (showString ";"), prt 0 xs]
 
 instance Print (Language.Rzk.Syntax.Abs.DeclUsedVars' a) where
@@ -198,8 +200,8 @@ instance Print (Language.Rzk.Syntax.Abs.Pattern' a) where
     Language.Rzk.Syntax.Abs.PatternPair _ pattern_1 pattern_2 -> prPrec i 0 (concatD [doc (showString "("), prt 0 pattern_1, doc (showString ","), prt 0 pattern_2, doc (showString ")")])
 
 instance Print [Language.Rzk.Syntax.Abs.Pattern' a] where
-  prt _ []     = concatD []
-  prt _ [x]    = concatD [prt 0 x]
+  prt _ [] = concatD []
+  prt _ [x] = concatD [prt 0 x]
   prt _ (x:xs) = concatD [prt 0 x, prt 0 xs]
 
 instance Print (Language.Rzk.Syntax.Abs.Param' a) where
@@ -210,8 +212,8 @@ instance Print (Language.Rzk.Syntax.Abs.Param' a) where
     Language.Rzk.Syntax.Abs.ParamPatternShapeDeprecated _ pattern_ term1 term2 -> prPrec i 0 (concatD [doc (showString "{"), prt 0 pattern_, doc (showString ":"), prt 0 term1, doc (showString "|"), prt 0 term2, doc (showString "}")])
 
 instance Print [Language.Rzk.Syntax.Abs.Param' a] where
-  prt _ []     = concatD []
-  prt _ [x]    = concatD [prt 0 x]
+  prt _ [] = concatD []
+  prt _ [x] = concatD [prt 0 x]
   prt _ (x:xs) = concatD [prt 0 x, prt 0 xs]
 
 instance Print (Language.Rzk.Syntax.Abs.ParamDecl' a) where
@@ -228,8 +230,8 @@ instance Print (Language.Rzk.Syntax.Abs.Restriction' a) where
     Language.Rzk.Syntax.Abs.ASCII_Restriction _ term1 term2 -> prPrec i 0 (concatD [prt 0 term1, doc (showString "|->"), prt 0 term2])
 
 instance Print [Language.Rzk.Syntax.Abs.Restriction' a] where
-  prt _ []     = concatD []
-  prt _ [x]    = concatD [prt 0 x]
+  prt _ [] = concatD []
+  prt _ [x] = concatD [prt 0 x]
   prt _ (x:xs) = concatD [prt 0 x, doc (showString ","), prt 0 xs]
 
 instance Print (Language.Rzk.Syntax.Abs.Term' a) where
@@ -289,6 +291,6 @@ instance Print (Language.Rzk.Syntax.Abs.Term' a) where
     Language.Rzk.Syntax.Abs.ASCII_Second _ term -> prPrec i 6 (concatD [doc (showString "second"), prt 7 term])
 
 instance Print [Language.Rzk.Syntax.Abs.Term' a] where
-  prt _ []     = concatD []
-  prt _ [x]    = concatD [prt 0 x]
+  prt _ [] = concatD []
+  prt _ [x] = concatD [prt 0 x]
   prt _ (x:xs) = concatD [prt 0 x, doc (showString ","), prt 0 xs]
diff --git a/rzk/src/Language/Rzk/Syntax/Skel.hs b/rzk/src/Language/Rzk/Syntax/Skel.hs
index a12862b25..f563fd074 100644
--- a/rzk/src/Language/Rzk/Syntax/Skel.hs
+++ b/rzk/src/Language/Rzk/Syntax/Skel.hs
@@ -1,4 +1,4 @@
--- File generated by the BNF Converter (bnfc 2.9.4.1).
+-- File generated by the BNF Converter (bnfc 2.9.5).
 
 -- Templates for pattern matching on abstract syntax
 
diff --git a/rzk/src/Language/Rzk/Syntax/Test.hs b/rzk/src/Language/Rzk/Syntax/Test.hs
new file mode 100644
index 000000000..a1f0dd00a
--- /dev/null
+++ b/rzk/src/Language/Rzk/Syntax/Test.hs
@@ -0,0 +1,78 @@
+-- File generated by the BNF Converter (bnfc 2.9.5).
+
+-- | Program to test parser.
+
+module Main where
+
+import Prelude
+  ( ($), (.)
+  , Bool(..)
+  , Either(..)
+  , Int, (>)
+  , String, (++), concat, unlines
+  , Show, show
+  , IO, (>>), (>>=), mapM_, putStrLn
+  , FilePath
+  , getContents, readFile
+  )
+import System.Environment ( getArgs )
+import System.Exit        ( exitFailure )
+import Control.Monad      ( when )
+
+import Language.Rzk.Syntax.Abs    ()
+import Language.Rzk.Syntax.Layout ( resolveLayout )
+import Language.Rzk.Syntax.Lex    ( Token, mkPosToken )
+import Language.Rzk.Syntax.Par    ( pModule, myLexer )
+import Language.Rzk.Syntax.Print  ( Print, printTree )
+import Language.Rzk.Syntax.Skel   ()
+
+type Err        = Either String
+type ParseFun a = [Token] -> Err a
+type Verbosity  = Int
+
+putStrV :: Verbosity -> String -> IO ()
+putStrV v s = when (v > 1) $ putStrLn s
+
+runFile :: (Print a, Show a) => Verbosity -> ParseFun a -> FilePath -> IO ()
+runFile v p f = putStrLn f >> readFile f >>= run v p
+
+run :: (Print a, Show a) => Verbosity -> ParseFun a -> String -> IO ()
+run v p s =
+  case p ts of
+    Left err -> do
+      putStrLn "\nParse              Failed...\n"
+      putStrV v "Tokens:"
+      mapM_ (putStrV v . showPosToken . mkPosToken) ts
+      putStrLn err
+      exitFailure
+    Right tree -> do
+      putStrLn "\nParse Successful!"
+      showTree v tree
+  where
+  ts = resolveLayout True $ myLexer s
+  showPosToken ((l,c),t) = concat [ show l, ":", show c, "\t", show t ]
+
+showTree :: (Show a, Print a) => Int -> a -> IO ()
+showTree v tree = do
+  putStrV v $ "\n[Abstract Syntax]\n\n" ++ show tree
+  putStrV v $ "\n[Linearized tree]\n\n" ++ printTree tree
+
+usage :: IO ()
+usage = do
+  putStrLn $ unlines
+    [ "usage: Call with one of the following argument combinations:"
+    , "  --help          Display this help message."
+    , "  (no arguments)  Parse stdin verbosely."
+    , "  (files)         Parse content of files verbosely."
+    , "  -s (files)      Silent mode. Parse content of files silently."
+    ]
+
+main :: IO ()
+main = do
+  args <- getArgs
+  case args of
+    ["--help"] -> usage
+    []         -> getContents >>= run 2 pModule
+    "-s":fs    -> mapM_ (runFile 0 pModule) fs
+    fs         -> mapM_ (runFile 2 pModule) fs
+
diff --git a/rzk/src/Language/Rzk/VSCode/Handlers.hs b/rzk/src/Language/Rzk/VSCode/Handlers.hs
index 55c61809c..d1b2bd01f 100644
--- a/rzk/src/Language/Rzk/VSCode/Handlers.hs
+++ b/rzk/src/Language/Rzk/VSCode/Handlers.hs
@@ -8,10 +8,11 @@ module Language.Rzk.VSCode.Handlers where
 
 import           Control.Exception             (SomeException, evaluate, try)
 import           Control.Lens
-import           Control.Monad.Cont            (MonadIO (liftIO), forM_)
+import           Control.Monad                 (forM_, when)
+import           Control.Monad.IO.Class        (MonadIO (..))
 import           Data.Default.Class
 import           Data.List                     (sort, (\\))
-import           Data.Maybe                    (fromMaybe)
+import           Data.Maybe                    (fromMaybe, isNothing)
 import qualified Data.Text                     as T
 import qualified Data.Yaml                     as Yaml
 import           Language.LSP.Diagnostics      (partitionBySource)
@@ -32,7 +33,8 @@ import           Language.Rzk.Free.Syntax      (RzkPosition (RzkPosition),
 import           Language.Rzk.Syntax           (Module, VarIdent' (VarIdent),
                                                 parseModuleFile, printTree)
 import           Language.Rzk.VSCode.Env
-import           Language.Rzk.VSCode.State     (ProjectConfig (include))
+import           Language.Rzk.VSCode.Logging
+import           Rzk.Project.Config            (ProjectConfig (include))
 import           Rzk.TypeCheck
 
 -- | Given a list of file paths, reads them and parses them as Rzk modules,
@@ -66,18 +68,21 @@ filePathToNormalizedUri = toNormalizedUri . filePathToUri
 
 typecheckFromConfigFile :: LSP ()
 typecheckFromConfigFile = do
+  logInfo "Looking for rzk.yaml"
   root <- getRootPath
   case root of
     Nothing -> do
+      logWarning "Workspace has no root path, cannot find rzk.yaml"
       sendNotification SMethod_WindowShowMessage (ShowMessageParams MessageType_Warning "Cannot find the workspace root")
     Just rootPath -> do
       let rzkYamlPath = rootPath </> "rzk.yaml"
       eitherConfig <- liftIO $ Yaml.decodeFileEither @ProjectConfig rzkYamlPath
       case eitherConfig of
         Left err -> do
-          sendNotification SMethod_WindowShowMessage (ShowMessageParams MessageType_Warning (T.pack $ "Invalid or missing rzk.yaml: " ++ Yaml.prettyPrintParseException err))
+          logError ("Invalid or missing rzk.yaml: " ++ Yaml.prettyPrintParseException err)
 
         Right config -> do
+          logDebug "Starting typechecking"
           rawPaths <- liftIO $ globDir (map compile (include config)) rootPath
           let paths = concatMap sort rawPaths
 
@@ -85,6 +90,9 @@ typecheckFromConfigFile = do
           let cachedPaths = map fst cachedModules
               modifiedFiles = paths \\ cachedPaths
 
+          logDebug ("Found " ++ show (length cachedPaths) ++ " files in the cache")
+          logDebug (show (length modifiedFiles) ++ " files have been modified")
+
           (parseErrors, parsedModules) <- liftIO $ collectErrors <$> parseFiles modifiedFiles
           tcResults <- liftIO $ try $ evaluate $
             defaultTypeCheck (typecheckModulesWithLocationIncremental cachedModules parsedModules)
@@ -94,11 +102,14 @@ typecheckFromConfigFile = do
             Right (Left err) -> return ([err], [])    -- sort of impossible
             Right (Right (checkedModules, errors)) -> do
                 -- cache well-typed modules
+                logInfo (show (length checkedModules) ++ " modules successfully typechecked")
+                logInfo (show (length errors) ++ " errors found")
                 cacheTypecheckedModules checkedModules
                 return (errors, checkedModules)
 
           -- Reset all published diags
           -- TODO: remove this after properly grouping by path below, after which there can be an empty list of errors
+          -- TODO: handle clearing diagnostics for files that got removed from the project (rzk.yaml)
           forM_ paths $ \path -> do
             publishDiagnostics 0 (filePathToNormalizedUri path) Nothing (partitionBySource [])
 
@@ -161,9 +172,12 @@ instance Default CompletionItemLabelDetails
 
 provideCompletions :: Handler LSP 'Method_TextDocumentCompletion
 provideCompletions req res = do
+  logInfo "Providing text completions"
   root <- getRootPath
+  when (isNothing root) $ logDebug "Not in a workspace. Cannot find root path for relative paths"
   let rootDir = fromMaybe "/" root
   cachedModules <- getCachedTypecheckedModules
+  logDebug ("Found " ++ show (length cachedModules) ++ " modules in the cache")
   let currentFile = fromMaybe "" $ uriToFilePath $ req ^. params . textDocument . uri
   -- Take all the modules up to and including the currently open one
   let modules = takeWhileInc ((/= currentFile) . fst) cachedModules
@@ -174,6 +188,7 @@ provideCompletions req res = do
             | otherwise = [x]
 
   let items = concatMap (declsToItems rootDir) modules
+  logDebug ("Sending " ++ show (length items) ++ " completion items")
   res $ Right $ InL items
   where
     declsToItems :: FilePath -> (FilePath, [Decl']) -> [CompletionItem]
diff --git a/rzk/src/Language/Rzk/VSCode/Logging.hs b/rzk/src/Language/Rzk/VSCode/Logging.hs
new file mode 100644
index 000000000..159eb29ac
--- /dev/null
+++ b/rzk/src/Language/Rzk/VSCode/Logging.hs
@@ -0,0 +1,20 @@
+module Language.Rzk.VSCode.Logging where
+
+import           Colog.Core           (Severity (..), WithSeverity (..), (<&))
+import qualified Data.Text            as T
+import           Language.LSP.Logging (defaultClientLogger)
+import           Language.LSP.Server  (MonadLsp)
+
+
+logDebug :: MonadLsp c m => String -> m ()
+logDebug msg = defaultClientLogger <& T.pack msg `WithSeverity` Debug
+
+logInfo :: MonadLsp c m => String -> m ()
+logInfo msg = defaultClientLogger <& T.pack msg `WithSeverity` Info
+
+logWarning :: MonadLsp c m => String -> m ()
+logWarning msg = defaultClientLogger <& T.pack msg `WithSeverity` Warning
+
+-- | Error logs will also be shown to the user via `window/showMessage`
+logError :: MonadLsp c m => String -> m ()
+logError msg = defaultClientLogger <& T.pack msg `WithSeverity` Error
diff --git a/rzk/src/Language/Rzk/VSCode/Lsp.hs b/rzk/src/Language/Rzk/VSCode/Lsp.hs
index c2a6a069f..d3514e583 100644
--- a/rzk/src/Language/Rzk/VSCode/Lsp.hs
+++ b/rzk/src/Language/Rzk/VSCode/Lsp.hs
@@ -1,6 +1,5 @@
 {-# LANGUAGE DuplicateRecordFields #-}
 {-# LANGUAGE OverloadedStrings     #-}
-{-# LANGUAGE TypeApplications      #-}
 
 module Language.Rzk.VSCode.Lsp where
 
@@ -20,6 +19,7 @@ import           Language.LSP.VFS              (virtualFileText)
 import           Language.Rzk.Syntax           (parseModuleSafe)
 import           Language.Rzk.VSCode.Env
 import           Language.Rzk.VSCode.Handlers
+import           Language.Rzk.VSCode.Logging
 import           Language.Rzk.VSCode.Tokenize  (tokenizeModule)
 
 -- | The maximum number of diagnostic messages to send to the client
@@ -39,12 +39,10 @@ handlers =
     , notificationHandler SMethod_WorkspaceDidChangeWatchedFiles $ \msg -> do
         let modifiedPaths = msg ^.. params . changes . traverse . uri . to uriToFilePath . _Just
         if any ("rzk.yaml" `isSuffixOf`) modifiedPaths
-          then resetCacheForAllFiles
+          then do
+            logDebug "rzk.yaml modified. Clearing module cache"
+            resetCacheForAllFiles
           else resetCacheForFiles modifiedPaths
-        -- TODO: see what files changed and typecheck them again
-        --  Need to handle 3 events: added, changed, and deleted
-
-        -- Currently, this is only sent for changes in `rzk.yaml`, so it makes sense to typecheck again (unconditionally)
         typecheckFromConfigFile
     , notificationHandler SMethod_TextDocumentDidSave $ \_msg -> do
         -- TODO: check if the file is included in the config's `include` list.
@@ -67,9 +65,9 @@ handlers =
               Just sourceCode -> fmap (fmap tokenizeModule) $ liftIO $
                 parseModuleSafe (T.unpack sourceCode)
         case possibleTokens of
-          Left _err -> do
+          Left err -> do
             -- Exception occurred when parsing the module
-            return ()
+            logWarning ("Failed to tokenize file: " ++ err)
           Right tokens -> do
             let encoded = encodeTokens defaultSemanticTokensLegend $ relativizeTokens tokens
             case encoded of
@@ -95,10 +93,12 @@ runLsp = do
   rzkEnv <- defaultRzkEnv
   runServer $
     ServerDefinition
-      { onConfigurationChange = const $ pure $ Right (),
-        doInitialize = const . pure . Right,
-        staticHandlers = const handlers,
-        interpretHandler = \env -> Iso (flip runReaderT rzkEnv . runLspT env) liftIO,
-        options = defaultOptions { optTextDocumentSync = Just syncOptions },
-        defaultConfig = ()
+      { configSection = "rzk"
+      , parseConfig = const . pure
+      , onConfigChange = const $ pure ()
+      , doInitialize = const . pure . Right
+      , staticHandlers = const handlers
+      , interpretHandler = \env -> Iso (flip runReaderT rzkEnv . runLspT env) liftIO
+      , options = defaultOptions { optTextDocumentSync = Just syncOptions }
+      , defaultConfig = ()
       }
diff --git a/rzk/src/Language/Rzk/VSCode/Tokenize.hs b/rzk/src/Language/Rzk/VSCode/Tokenize.hs
index 35fb006e9..0a60bdee1 100644
--- a/rzk/src/Language/Rzk/VSCode/Tokenize.hs
+++ b/rzk/src/Language/Rzk/VSCode/Tokenize.hs
@@ -6,7 +6,6 @@ import           Language.LSP.Protocol.Types (SemanticTokenAbsolute (..),
                                               SemanticTokenModifiers (..),
                                               SemanticTokenTypes (..))
 import           Language.Rzk.Syntax
-import           Language.Rzk.Syntax.Print
 
 tokenizeModule :: Module -> [SemanticTokenAbsolute]
 tokenizeModule (Module _loc langDecl commands) = concat
diff --git a/rzk/src/Rzk/Main.hs b/rzk/src/Rzk/Main.hs
index 187b40255..ecd750184 100644
--- a/rzk/src/Rzk/Main.hs
+++ b/rzk/src/Rzk/Main.hs
@@ -3,21 +3,28 @@
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE LambdaCase        #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+{-# LANGUAGE TypeApplications  #-}
 
 module Rzk.Main where
 
 import           Control.Monad           (forM, void)
 import           Data.List               (sort)
 import           Data.Version            (showVersion)
-#ifndef __GHCJS__
+
+#ifdef LSP
 import           Language.Rzk.VSCode.Lsp (runLsp)
 #endif
+
+import qualified Data.Yaml               as Yaml
 import           Options.Generic
+import           System.Directory        (doesPathExist)
 import           System.Exit             (exitFailure)
 import           System.FilePath.Glob    (glob)
 
 import qualified Language.Rzk.Syntax     as Rzk
 import           Paths_rzk               (version)
+import           Rzk.Project.Config
 import           Rzk.TypeCheck
 
 data Command
@@ -41,10 +48,10 @@ main = getRecord "rzk: an experimental proof assistant for synthetic ∞-categor
       Right _decls -> putStrLn "Everything is ok!"
 
   Lsp ->
-#ifndef __GHCJS__
+#ifdef LSP
     void runLsp
 #else
-    error "rzk lsp is not supported with a GHCJS build"
+    error "rzk lsp is not supported with this build"
 #endif
 
   Version -> putStrLn (showVersion version)
@@ -66,12 +73,29 @@ globNonEmpty path = do
     []    -> error ("File(s) not found at " <> path)
     paths -> return (sort paths)
 
+extractFilesFromRzkYaml :: FilePath -> IO [FilePath]
+extractFilesFromRzkYaml rzkYamlPath = do
+  eitherConfig <- Yaml.decodeFileEither @ProjectConfig rzkYamlPath
+  case eitherConfig of
+    Left err -> do
+      error ("Invalid or missing rzk.yaml: " ++ Yaml.prettyPrintParseException err)
+    Right ProjectConfig{..} -> do
+      return include
+
 parseRzkFilesOrStdin :: [FilePath] -> IO [(FilePath, Rzk.Module)]
 parseRzkFilesOrStdin = \case
   -- if no paths are given β€” read from stdin
   [] -> do
-    rzkModule <- parseStdin
-    return [("<stdin>", rzkModule)]
+    let rzkYamlPath = "rzk.yaml"
+    rzkYamlExists <- doesPathExist rzkYamlPath
+    if rzkYamlExists
+      then do
+        putStrLn ("Using Rzk project stucture specified in " <> rzkYamlPath)
+        paths <- extractFilesFromRzkYaml rzkYamlPath
+        parseRzkFilesOrStdin paths
+      else do
+        rzkModule <- parseStdin
+        return [("<stdin>", rzkModule)]
   -- otherwise β€” parse all given files in given order
   paths -> do
     expandedPaths <- foldMap globNonEmpty paths
@@ -87,7 +111,7 @@ parseRzkFilesOrStdin = \case
 typecheckString :: String -> Either String String
 typecheckString moduleString = do
   rzkModule <- Rzk.parseModule moduleString
-  case defaultTypeCheck (typecheckModule Nothing rzkModule) of
+  case defaultTypeCheck (typecheckModules [rzkModule]) of
     Left err -> Left $ unlines
       [ "An error occurred when typechecking!"
       , "Rendering type error... (this may take a few seconds)"
diff --git a/rzk/src/Language/Rzk/VSCode/State.hs b/rzk/src/Rzk/Project/Config.hs
similarity index 78%
rename from rzk/src/Language/Rzk/VSCode/State.hs
rename to rzk/src/Rzk/Project/Config.hs
index 3e70ddb34..268a89182 100644
--- a/rzk/src/Language/Rzk/VSCode/State.hs
+++ b/rzk/src/Rzk/Project/Config.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 
-module Language.Rzk.VSCode.State where
+module Rzk.Project.Config where
 
 import           Data.Yaml (FromJSON (..), (.!=), (.:), (.:?))
 import qualified Data.Yaml as Y
@@ -16,5 +16,3 @@ instance FromJSON ProjectConfig where
     v .:  "include" <*>
     v .:? "exclude" .!= []
   parseJSON _ = fail "Expected config value to be an object"
-
--- TODO: Add a "ServerState" data structure for holding the typechecking cache
diff --git a/rzk/src/Rzk/TypeCheck.hs b/rzk/src/Rzk/TypeCheck.hs
index 2792bec4d..c94a7b786 100644
--- a/rzk/src/Rzk/TypeCheck.hs
+++ b/rzk/src/Rzk/TypeCheck.hs
@@ -10,6 +10,7 @@
 module Rzk.TypeCheck where
 
 import           Control.Applicative      ((<|>))
+import           Control.Monad            (forM, forM_, join, unless, when)
 import           Control.Monad.Except
 import           Control.Monad.Reader
 import           Data.Bifunctor           (first)
@@ -88,12 +89,12 @@ typecheckModules = \case
   [] -> return []
   m : ms -> do
     (decls, errs) <- typecheckModule Nothing m
-    if null errs
-      then
+    case errs of
+      err : _ -> do
+        throwError err
+      _ -> do
         localDeclsPrepared decls $
           (decls <>) <$> typecheckModules ms
-      else
-        return decls
 
 typecheckModuleWithLocation :: (FilePath, Rzk.Module) -> TypeCheck VarIdent ([Decl'], [TypeErrorInScopedContext VarIdent])
 typecheckModuleWithLocation (path, module_) = do
@@ -1938,14 +1939,23 @@ unifyInCurrentContext mterm expected actual = performing action $
                     switchVariance $  -- unifying in the negative position!
                       unifyTerms cube cube' -- FIXME: unifyCubes
                     enterScope orig' cube $ do
-                      case (mtope, mtope') of
-                        (Just tope, Just tope') -> do
-                          topeNF <- nfT tope
-                          topeNF' <- nfT tope'
-                          unifyTopes topeNF topeNF'
-                        (Nothing, Nothing)      -> return ()
-                        (Just tope, Nothing)    -> nfT tope >>= (`unifyTopes` topeTopT)
-                        (Nothing, Just tope)    -> nfT tope >>= unifyTopes topeTopT
+                      case ret' of
+                        -- UniverseTopeT{} ->
+                        --   (Just tope, Just tope') -> do
+                        --     topeNF <- nfT tope
+                        --     topeNF' <- nfT tope'
+                        --     unifyTopes topeNF topeNF'
+                        --   (Nothing, Nothing)      -> return ()
+                        --   (Just tope, Nothing)    -> nfT tope >>= (`unifyTopes` topeTopT)
+                        --   (Nothing, Just tope)    -> nfT tope >>= unifyTopes topeTopT
+                        _ -> case (mtope, mtope') of
+                          (Just tope, Just tope') -> do
+                            topeNF <- nfT tope
+                            topeNF' <- nfT tope'
+                            unifyTopes topeNF topeNF'
+                          (Nothing, Nothing)      -> return ()
+                          (Just tope, Nothing)    -> nfT tope >>= (`unifyTopes` topeTopT)
+                          (Nothing, Just tope)    -> nfT tope >>= unifyTopes topeTopT
                       case mterm of
                         Nothing -> unifyTerms ret ret'
                         Just term -> unifyTypes (appT ret' (S <$> term) (Pure Z)) ret ret'
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 000000000..e479ab41d
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,10 @@
+let t = (import
+  (
+    let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
+    fetchTarball {
+      url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
+      sha256 = lock.nodes.flake-compat.locked.narHash;
+    }
+  )
+  { src = ./.; }
+).shellNix; in t // t.devShells.${builtins.currentSystem}
\ No newline at end of file
diff --git a/snapshot.yaml b/snapshot.yaml
deleted file mode 100644
index 768bd4ac3..000000000
--- a/snapshot.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-resolver: nightly-2023-04-09
-name: rzk-snapshot
-packages:
-  - with-utf8-1.0.2.4
-  - lsp-2.1.0.0
-  - lsp-types-2.0.1.0
-  - row-types-1.0.1.2
-  
\ No newline at end of file
diff --git a/stack-8.6.5.yaml b/stack-8.6.5.yaml
deleted file mode 100644
index 1a279c5be..000000000
--- a/stack-8.6.5.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-resolver:
-  url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/27.yaml
-
-packages:
-  - rzk/
-
-flags:
-  rzk:
-    lsp: false
\ No newline at end of file
diff --git a/stack-8.6.5.yaml.lock b/stack-8.6.5.yaml.lock
deleted file mode 100644
index 9c3fafaaf..000000000
--- a/stack-8.6.5.yaml.lock
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file was autogenerated by Stack.
-# You should not edit this file by hand.
-# For more information, please see the documentation at:
-#   https://docs.haskellstack.org/en/stable/lock_files
-
-packages: []
-snapshots:
-- completed:
-    sha256: 7ea31a280c56bf36ff591a7397cc384d0dff622e7f9e4225b47d8980f019a0f0
-    size: 524996
-    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/27.yaml
-  original:
-    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/27.yaml
diff --git a/stack.yaml b/stack.yaml
index 8ffec6992..53ac76292 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,4 +1,3 @@
-resolver: snapshot.yaml
+resolver: nightly-2023-09-30
 packages:
   - rzk
-  
\ No newline at end of file
diff --git a/stack.yaml.lock b/stack.yaml.lock
index f35834ac6..a51a2da7e 100644
--- a/stack.yaml.lock
+++ b/stack.yaml.lock
@@ -3,38 +3,10 @@
 # For more information, please see the documentation at:
 #   https://docs.haskellstack.org/en/stable/lock_files
 
-packages:
-- completed:
-    hackage: with-utf8-1.0.2.4@sha256:c47c077769883cc54a18ea0a6567c5b49fd2ab708f796ec92b8ad3c8b60a8b09,2974
-    pantry-tree:
-      sha256: af0f438235d84ce1ea04f1e8ad566d1aeeb287515adae3d2843c309f4d031651
-      size: 1051
-  original:
-    hackage: with-utf8-1.0.2.4
-- completed:
-    hackage: lsp-2.1.0.0@sha256:ef6fc28eac6dc27672cd8471c9f83f14de646a9c1fcaf993a451d2ae4de274e8,3533
-    pantry-tree:
-      sha256: 1ace37e19271024b6396c8ef0ebe9410b5fe578d70ef2cfa0f58990ae975fe0c
-      size: 1043
-  original:
-    hackage: lsp-2.1.0.0
-- completed:
-    hackage: lsp-types-2.0.1.0@sha256:70a822473de72c165495c2eed00f4c2a728f7fe1e6d7d8b4709d474a41860940,29317
-    pantry-tree:
-      sha256: 9aa011ac9899699570a7085e10957be306bdb78262f24ac2366d56c1bd9e6711
-      size: 45522
-  original:
-    hackage: lsp-types-2.0.1.0
-- completed:
-    hackage: row-types-1.0.1.2@sha256:4d4c7cb95d06a32b28ba977852d52a26b4c1f695ef083a6fd874ab6d79933b64,3071
-    pantry-tree:
-      sha256: 6a3617038d3970095100d14d026c396002a115700500cf3004ffb67ae5a75611
-      size: 1060
-  original:
-    hackage: row-types-1.0.1.2
+packages: []
 snapshots:
 - completed:
-    sha256: cbf721fafa21237e4999d83cfd27137f440ae0e3032ff18fa96e8148d9bf5ce1
-    size: 604108
-    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2023/4/9.yaml
-  original: nightly-2023-04-09
+    sha256: 402c22fcb980c23c960ce8249d20c572f26abb1395a5d581e71244e7635bc578
+    size: 670169
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2023/9/30.yaml
+  original: nightly-2023-09-30
diff --git a/try-rzk/Main.hs b/try-rzk/Main.hs
deleted file mode 100644
index 471a63869..000000000
--- a/try-rzk/Main.hs
+++ /dev/null
@@ -1,80 +0,0 @@
--- | Haskell language pragma
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-# LANGUAGE TypeApplications  #-}
-
--- | Haskell module declaration
-module Main where
-
--- | Miso framework import
-import           Miso
-import           Miso.String
-import qualified GHCJS.Foreign.Callback as GHCJS
-import           GHCJS.Marshal (fromJSVal)
-import           GHCJS.Prim (JSVal)
-
-import qualified Rzk.Main as Rzk
-
--- | Type synonym for an application model
-data Model = Model
-  { response :: MisoString }
-  deriving (Show, Eq)
-
--- | Sum type for application events
-data Action
-  = Reload
-  | NoOp
-  | Check MisoString
-  deriving (Show, Eq)
-
--- | Entry point for a miso application
-main :: IO ()
-main = startApp App {..}
-  where
-    initialAction = Reload -- initial action to be executed on application load
-    model  = initModel            -- initial model
-    update = updateModel          -- update function
-    view   = viewModel            -- view function
-    events = defaultEvents        -- default delegated events
-    subs   = [ ctrlEnterSub ]
-    mountPoint = Just "__app__"   -- mount point for application (Nothing defaults to 'body')
-    logLevel = Off                -- used during prerendering to see if the VDOM and DOM are in sync (only used with `miso` function)
-
-ctrlEnterSub :: Sub Action
-ctrlEnterSub sink = do
-  callback <- GHCJS.asyncCallback1 $ \inputVal -> do
-    Just input <- fromJSVal inputVal
-    sink (Check input)
-  set__rzk__trigger_Check_callback callback
-
-initModel :: Model
-initModel = Model
-  { response = "loading..." }
-
--- | Updates model, optionally introduces side effects
-updateModel :: Action -> Model -> Effect Action Model
-updateModel NoOp m = noEff m
-updateModel Reload m = initModel <# do
-  Check <$> codemirrorGetValue
-updateModel (Check input) m = noEff m
-  { response = responseStr }
-  where
-    responseStr = ms $
-      case Rzk.typecheckString (fromMisoString input) of
-        Left err -> err
-        Right ok -> ok
-
--- | Constructs a virtual DOM from a model
-viewModel :: Model -> View Action
-viewModel Model{..} = div_ [] [
-   button_ [ onClick Reload ] [ text "Typecheck (Ctrl + Enter)" ]
- , br_ []
- , br_ []
- , pre_ [] [ text (ms response) ]
- ]
-
-foreign import javascript unsafe "$r = myCodeMirror.getValue();"
-  codemirrorGetValue :: IO MisoString
-
-foreign import javascript unsafe "__rzk__trigger_Check = $1"
-  set__rzk__trigger_Check_callback :: (GHCJS.Callback (JSVal -> IO ())) -> IO ()
diff --git a/try-rzk/README.md b/try-rzk/README.md
deleted file mode 100644
index 8b1378917..000000000
--- a/try-rzk/README.md
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/try-rzk/cabal.config b/try-rzk/cabal.config
deleted file mode 100644
index ef1b74964..000000000
--- a/try-rzk/cabal.config
+++ /dev/null
@@ -1 +0,0 @@
-compiler: ghcjs
diff --git a/try-rzk/default.nix b/try-rzk/default.nix
deleted file mode 100644
index 55570b513..000000000
--- a/try-rzk/default.nix
+++ /dev/null
@@ -1,6 +0,0 @@
-with (import (builtins.fetchTarball {
-  url = "https://github.com/dmjio/miso/archive/refs/tags/1.8.3.tar.gz";
-  /* sha256 = "1yb9yvc0ln4yn1jk2k5kwwa1s32310abawz40yd8cqqkm1z7w6wg"; */
-}) {});
-let rzk-local = pkgs.haskell.packages.ghcjs.callPackage ../rzk/rzk.nix { };
-in pkgs.haskell.packages.ghcjs.callCabal2nix "try-rzk" ./. { rzk = rzk-local; }
diff --git a/try-rzk/index.html b/try-rzk/index.html
deleted file mode 100644
index 9f0b22ab2..000000000
--- a/try-rzk/index.html
+++ /dev/null
@@ -1,354 +0,0 @@
-<html>
-  <head>
-    <title>Try Rzk proof assistant!</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-    <link rel="apple-touch-icon" sizes="180x180" href="/rzk/apple-touch-icon.png">
-    <link rel="icon" type="image/png" sizes="32x32" href="/rzk/favicon-32x32.png">
-    <link rel="icon" type="image/png" sizes="16x16" href="/rzk/favicon-16x16.png">
-    <link rel="manifest" href="/rzk/site.webmanifest">
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/addon/mode/simple.min.js"></script>
-
-    <!-- Load local GHCJS application if possible -->
-    <script src="result/bin/try-rzk.jsexe/all.js"></script>
-    <!-- Otherwise load the one hosted on GitHub Pages -->
-    <script>window.h$mainLoop || document.write('<script src="https://rzk-lang.github.io/rzk/result/bin/try-rzk.jsexe/all.js"><\/script>')</script>
-
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.css">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/theme/solarized.min.css">
-    <link rel="stylesheet" href="https://codemirror.net/5/theme/gruvbox-dark.css">
-    <style>
-      section { width: 100%; }
-      body { margin: 0; background-color: #000; }
-      .row { display: flex; justify-content:space-evenly; margin: 0; padding: 0; width: 100%; }
-      .column { margin-top: 0; margin-bottom: 0; width: 100%;  }
-      #__codemirror__ { height: 60vh; }
-      .CodeMirror { height: 60vh; font-family: Inconsolata, monospace; }
-      #__response__ { height: 40vh; }
-
-      /* CSS for response button from https://getcssscan.com/css-buttons-examples (button 61) */
-      #__response__ button {
-        align-items: center;
-        appearance: none;
-        border-radius: 4px;
-        border-style: none;
-        box-shadow: rgba(0, 0, 0, .2) 0 3px 1px -2px,rgba(0, 0, 0, .14) 0 2px 2px 0,rgba(0, 0, 0, .12) 0 1px 5px 0;
-        box-sizing: border-box;
-        color: #fff;
-        cursor: pointer;
-        display: inline-flex;
-        font-family: Roboto,sans-serif;
-        font-size: .875rem;
-        font-weight: 500;
-        height: 36px;
-        justify-content: center;
-        letter-spacing: .0892857em;
-        line-height: normal;
-        min-width: 64px;
-        outline: none;
-        overflow: visible;
-        padding: 0 16px;
-        position: relative;
-        text-align: center;
-        text-decoration: none;
-        text-transform: uppercase;
-        transition: box-shadow 280ms cubic-bezier(.4, 0, .2, 1);
-        user-select: none;
-        -webkit-user-select: none;
-        touch-action: manipulation;
-        vertical-align: middle;
-        will-change: transform,opacity;
-      }
-
-      #__response__ button:hover {
-        box-shadow: rgba(0, 0, 0, .2) 0 2px 4px -1px, rgba(0, 0, 0, .14) 0 4px 5px 0, rgba(0, 0, 0, .12) 0 1px 10px 0;
-      }
-
-      #__response__ button:disabled {
-        background-color: rgba(0, 0, 0, .12);
-        box-shadow: rgba(0, 0, 0, .2) 0 0 0 0, rgba(0, 0, 0, .14) 0 0 0 0, rgba(0, 0, 0, .12) 0 0 0 0;
-        color: rgba(0, 0, 0, .37);
-        cursor: default;
-        pointer-events: none;
-      }
-
-      #__response__ button:not(:disabled) {
-        background-color: #6200ee;
-      }
-
-      #__response__ button:focus {
-        box-shadow: rgba(0, 0, 0, .2) 0 2px 4px -1px, rgba(0, 0, 0, .14) 0 4px 5px 0, rgba(0, 0, 0, .12) 0 1px 10px 0;
-      }
-
-      #__response__ button:active {
-        box-shadow: rgba(0, 0, 0, .2) 0 5px 5px -3px, rgba(0, 0, 0, .14) 0 8px 10px 1px, rgba(0, 0, 0, .12) 0 3px 14px 2px;
-        background: #A46BF5;
-      }
-
-      #__response__ { background-color: #202028; color: #eee8d5; overflow: scroll; }
-      #__response__ pre { font-family: Inconsolata, monospace; }
-    </style>
-  </head>
-  <body class="cm-c-gruvbox-dark">
-    <div class="row">
-      <div class="column" id="__codemirror__">
-      </div>
-    </div>
-    <div class="row">
-      <div class="column" id="__response__">
-        <div id="__app__" style="margin: 20px"></div>
-      </div>
-    </div>
-
-    <script>
-      // adapted from https://stackoverflow.com/a/28828681/442535
-      function getText(url){
-          // read text from URL location
-          var request = new XMLHttpRequest();
-          request.open('GET', url, true);
-          request.send(null);
-          request.onreadystatechange = function () {
-              if (request.readyState === 4 && request.status === 200) {
-                  var type = request.getResponseHeader('Content-Type');
-                  if (type.indexOf("text") !== 1) {
-                      return request.responseText;
-                  }
-              }
-          }
-      }
-
-      CodeMirror.defineSimpleMode("rzk-stlc", {
-        // The start state contains the rules that are initially used
-        start: [
-          {regex: /#(infer|unify|typecheck|whnf|nf|def)/, token: "meta"},
-          // Rules are matched in the order in which they appear, so there is
-          // no ambiguity between this one and the one above
-          {regex: /(?:U)\b/,
-           token: "keyword"},
-          {regex: /(?:\\|Ξ»)\b/,
-           token: "meta"},
-          // A next property will cause the mode to move to a different state
-          // {regex: /\/\*/, token: "comment", next: "comment"},
-          // {regex: /[-+\/*=<>!]+/, token: "operator"},
-          // indent and dedent properties guide autoindentation
-          {regex: /[\{\[\(]/, indent: true},
-          {regex: /[\}\]\)]/, dedent: true},
-          {regex: /([\w][^\s]*)(\s+:)/, token: ["variable-2", null]},
-          {regex: /[\w][^\s]*/, token: "variable"},
-          {regex: /--.*/, token: "comment"}
-        ],
-        // The meta property contains global information about the mode. It
-        // can contain properties like lineComment, which are supported by
-        // all modes, and also directives like dontIndentStates, which are
-        // specific to simple modes.
-        meta: {
-          dontIndentStates: ["comment"],
-          lineComment: "--"
-        }
-      });
-
-      CodeMirror.defineSimpleMode("rzk-mltt", {
-        // The start state contains the rules that are initially used
-        start: [
-          {regex: /#(infer|unify|typecheck|whnf|nf|def)/, token: "meta"},
-          // Rules are matched in the order in which they appear, so there is
-          // no ambiguity between this one and the one above
-          {regex: /(?:U)\b/,
-           token: "keyword"},
-          {regex: /(?:\\|Ξ»|=)\b/,
-           token: "meta"},
-          // A next property will cause the mode to move to a different state
-          // {regex: /\/\*/, token: "comment", next: "comment"},
-          // {regex: /[-+\/*=<>!]+/, token: "operator"},
-          // indent and dedent properties guide autoindentation
-          {regex: /refl|J|first|second|π₁|Ο€β‚‚|\*|Γ—|β†’|->/, token: "atom"},
-          {regex: /[\{\[\(]/, indent: true},
-          {regex: /[\}\]\)]/, dedent: true},
-          {regex: /([\w][^\s]*)(\s+:)/, token: ["variable-2", null]},
-          {regex: /[\w][^\s]*/, token: "variable"},
-          {regex: /--.*/, token: "comment"}
-        ],
-        // The meta property contains global information about the mode. It
-        // can contain properties like lineComment, which are supported by
-        // all modes, and also directives like dontIndentStates, which are
-        // specific to simple modes.
-        meta: {
-          dontIndentStates: ["comment"],
-          lineComment: "--"
-        }
-      });
-
-
-      CodeMirror.defineSimpleMode("rzk-pcf", {
-        // The start state contains the rules that are initially used
-        start: [
-          {regex: /#(infer|unify|typecheck|whnf|nf|def)/, token: "meta"},
-          // Rules are matched in the order in which they appear, so there is
-          // no ambiguity between this one and the one above
-          {regex: /(?:U|NAT|UNIT|BOOL)\b/,
-           token: "keyword"},
-          {regex: /(?:\\|Ξ»)\b/,
-           token: "meta"},
-          {regex: /(?:if|then|else)\b/,
-           token: "keyword"},
-          {regex: /unit|false|true|fix|mul|pred|isZero|\*/, token: "atom"},
-          {regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
-           token: "number"},
-          {regex: /\/(?:[^\\]|\\.)*?\//, token: "variable-3"},
-          // A next property will cause the mode to move to a different state
-          // {regex: /\/\*/, token: "comment", next: "comment"},
-          // {regex: /[-+\/*=<>!]+/, token: "operator"},
-          // indent and dedent properties guide autoindentation
-          {regex: /[\{\[\(]/, indent: true},
-          {regex: /[\}\]\)]/, dedent: true},
-          {regex: /([\w][^\s]*)(\s+:)/, token: ["variable-2", null]},
-          {regex: /[\w][^\s]*/, token: "variable"},
-          {regex: /--.*/, token: "comment"}
-        ],
-        // The meta property contains global information about the mode. It
-        // can contain properties like lineComment, which are supported by
-        // all modes, and also directives like dontIndentStates, which are
-        // specific to simple modes.
-        meta: {
-          dontIndentStates: ["comment"],
-          lineComment: "--"
-        }
-      });
-
-      CodeMirror.defineSimpleMode("rzk-1", {
-        // The start state contains the rules that are initially used
-        start: [
-          {regex: /#(infer|unify|typecheck|whnf|nf|def)/, token: "meta"},
-          // The regex matches the token, the token property contains the type
-          {regex: /"(?:[^\\]|\\.)*?(?:"|$)/, token: "string"},
-          // You can match multiple tokens at once. Note that the captured
-          // groups must span the whole string in this case
-          {regex: /(refl)(_{)([\w$]*)(})/,
-           token: ["keyword", null, "comment", null]},
-          {regex: /({\s*)([^\|]*)(\s+\|\s+)([^}]*)(\s*})/,
-           token: ["qualifier", "variable", "qualifier", "meta", "qualifier"]},
-          {regex: /(\[\s*)([^\|]*)(\s+\|->\s+)([^\]]*)(\s*\])/,
-           token: ["qualifier", "meta", "qualifier", "property", "qualifier"]},
-          {regex: /(=)(_{)([\w$]*)(})/,
-           token: ["keyword", null, "comment", null]},
-          // Rules are matched in the order in which they appear, so there is
-          // no ambiguity between this one and the one above
-          {regex: /(?:CUBE|TOPE|U)\b/,
-           token: "keyword"},
-          {regex: /true|false|null|undefined/, token: "atom"},
-          {regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
-           token: "number"},
-          {regex: /\/(?:[^\\]|\\.)*?\//, token: "variable-3"},
-          // A next property will cause the mode to move to a different state
-          {regex: /--.*/, token: "comment"},
-          // {regex: /[-+\/*=<>!]+/, token: "operator"},
-          // indent and dedent properties guide autoindentation
-          {regex: /[\{\[\(]/, indent: true},
-          {regex: /[\}\]\)]/, dedent: true},
-          {regex: /([\w][^\s]*)(\s+:)/, token: ["variable-2", null]},
-          {regex: /[\w][^\s]*/, token: "variable"},
-          // You can embed other modes with the mode property. This rule
-          // causes all code between << and >> to be highlighted with the XML
-          // mode.
-          {regex: /<</, token: "meta", mode: {spec: "xml", end: />>/}}
-        ],
-        // The multi-line comment state.
-        comment: [
-          {regex: /.*?\*\//, token: "comment", next: "start"},
-          {regex: /.*/, token: "comment"}
-        ],
-        // The meta property contains global information about the mode. It
-        // can contain properties like lineComment, which are supported by
-        // all modes, and also directives like dontIndentStates, which are
-        // specific to simple modes.
-        meta: {
-          dontIndentStates: ["comment"],
-          lineComment: "--"
-        }
-      });
-
-      CodeMirror.defineSimpleMode("rzk-poly", {
-        // The start state contains the rules that are initially used
-        start: [
-          {regex: /(#lang)( pcf)/,  token: ["attribute", "keyword"], mode: {spec: "rzk-pcf", end: /eof/}},
-          {regex: /(#lang)( stlc)/,  token: ["attribute", "keyword"], mode: {spec: "rzk-stlc", end: /eof/}},
-          {regex: /(#lang)( mltt)/,  token: ["attribute", "keyword"], mode: {spec: "rzk-mltt", end: /eof/}},
-          {regex: /(#lang)( rzk-1)/, token: ["attribute", "keyword"], mode: {spec: "rzk-1", end: /eof/}}
-        ],
-        // The meta property contains global information about the mode. It
-        // can contain properties like lineComment, which are supported by
-        // all modes, and also directives like dontIndentStates, which are
-        // specific to simple modes.
-        meta: {
-          dontIndentStates: ["comment"],
-          lineComment: "--"
-        }
-      });
-
-      /* extract query parameters from the URL */
-      const params = new URLSearchParams(window.location.search);
-
-      /* set up CodeMirror in the __textarea__ div */
-      var frame = document.getElementById("__codemirror__");
-      var myCodeMirror = CodeMirror(frame, {
-        lineNumbers: true,
-        value: "function myScript(){return 100;}\n",
-        mode:  "rzk-poly",
-        viewportMargin: Infinity,
-        indentUnit: 2,
-        smartIndent: true,
-        tabSize: 2,
-        theme: "gruvbox-dark"
-      });
-
-      snippet_rzk1 = "#lang rzk-1\n\n-- A is contractible there exists x : A such that for any y : A we have x = y.\n#def iscontr (A : U) : U\n  := βˆ‘ (a : A), (x : A) -> a =_{A} x\n\n-- A is a proposition if for any x, y : A we have x = y\n#def isaprop (A : U) : U\n  := (x : A) -> (y : A) -> x =_{A} y\n\n-- A is a set if for any x, y : A the type x =_{A} y is a proposition\n#def isaset (A : U) : U\n  := (x : A) -> (y : A) -> isaprop (x =_{A} y)\n\n-- Non-dependent product of A and B\n#def prod (A : U) (B : U) : U\n  := βˆ‘ (x : A), B\n\n-- A function f : A -> B is an equivalence\n-- if there exists g : B -> A\n-- such that for all x : A we have g (f x) = x\n-- and for all y : B we have f (g y) = y\n#def isweq (A : U) (B : U) (f : A -> B) : U\n  := βˆ‘ (g : B -> A), prod ((x : A) -> g (f x) =_{A} x) ((y : B) -> f (g y) =_{B} y)\n\n-- Equivalence of types A and B\n#def weq (A : U) (B : U) : U\n  := βˆ‘ (f : A -> B), isweq A B f\n\n-- Transport along a path\n#def transport\n    (A : U)\n    (C : A -> U)\n    (x y : A)\n    (p : x =_{A} y)\n    : C x -> C y\n  := \\cx -> idJ(A, x, (\\z q -> C z), cx, y, p)\n\n-- [RS17, Axiom 4.6] Relative function extensionality.\n#def relfunext : U\n  := (I : CUBE)\n  -> (psi : I -> TOPE)\n  -> (phi : psi -> TOPE)\n  -> (A : psi -> U)\n  -> ((t : psi) -> iscontr (A t))\n  -> (a : (t : phi) -> A t)\n  -> (t : psi) -> A t [ phi t |-> a t]\n\n-- [RS17, Proposition 4.8] A (weaker) formulation of function extensionality.\n#def relfunext2 : U\n  := (I : CUBE)\n  -> (psi : I -> TOPE)\n  -> (phi : psi -> TOPE)\n  -> (A : psi -> U)\n  -> (a : (t : phi) -> A t)\n  -> (f : (t : psi) -> A t [ phi t |-> a t ])\n  -> (g : (t : psi) -> A t [ phi t |-> a t ])\n  -> weq (f = g)\n         ((t : psi) -> (f t =_{A t} g t) [ phi t |-> refl ])\n\n-- Restrict extension type to a subshape.\n#def restrict\n    (I : CUBE)\n    (psi : I -> TOPE)\n    (phi : I -> TOPE)\n    (A : {t : I | psi t \\/ phi t} -> U)\n    (a : {t : I | psi t} -> A t)\n  : {t : I | psi t /\\ phi t} -> A t\n  := \\t -> a t\n\n-- Reformulate extension type as an extension of a restriction.\n#def ext-of-restrict\n    (I : CUBE)\n    (psi : I -> TOPE)\n    (phi : I -> TOPE)\n    (A : {t : I | psi t \\/ phi t} -> U)\n    (a : {t : I | psi t} -> A t)\n  : (t : psi) -> A t [ psi t /\\ phi t |-> restrict I psi phi A a t ]\n  := a\n\n-- Transform extension of an identity into an identity of restrictions.\n#def restricts-path\n    (r : relfunext2)\n    (I : CUBE)\n    (psi : I -> TOPE)\n    (phi : I -> TOPE)\n    (A : {t : I | psi t \\/ phi t} -> U)\n    (a_psi : (t : psi) -> A t)\n    (a_phi : (t : phi) -> A t)\n    (e : {t : I | psi t /\\ phi t} -> a_psi t = a_phi t)\n  : restrict I psi phi A a_psi = restrict I phi psi A a_phi\n  := (first (second (r I\n      (\\t -> psi t /\\ phi t)\n      (\\t -> BOT)\n      (\\t -> A t)\n      (\\t -> recBOT)\n      (\\t -> a_psi t)\n      (\\t -> a_phi t)))) e\n\n-- A weaker version of recOR, demanding only a path between a and b:\n-- recOR(psi, phi, a, b) demands that for psi /\\ phi we have a == b (definitionally)\n-- (recId psi phi a b e) demands that e is the proof that a = b (intensionally) for psi /\\ phi\n#def recId\n    (r : relfunext2)\n    (I : CUBE)\n    (psi : I -> TOPE)\n    (phi : I -> TOPE)\n    (A : {t : I | psi t \\/ phi t} -> U)\n    (a_psi : (t : psi) -> A t)\n    (a_phi : (t : phi) -> A t)\n    (e : {t : I | psi t /\\ phi t} -> a_psi t = a_phi t)\n  : {t : I | psi t \\/ phi t} -> A t\n  := \\t -> recOR(\n        psi t |-> transport\n          ({t : I | psi t /\\ phi t} -> A t)\n          (\\ra -> (t : psi) -> A t [ psi t /\\ phi t |-> ra t])\n          (restrict I psi phi A a_psi)\n          (restrict I phi psi A a_phi)\n          (restricts-path r I psi phi A a_psi a_phi e)\n          (ext-of-restrict I psi phi A a_psi)\n          t,\n        phi t |-> ext-of-restrict I phi psi A a_phi t\n      )\n\n-- If two extension types are equal along two subshapes,\n-- then they are also equal along their union.\n#def id-along-border\n    (r : relfunext2)\n    (I : CUBE)\n    (psi : I -> TOPE)\n    (phi : I -> TOPE)\n    (A : {t : I | psi t \\/ phi t} -> U)\n    (a b : {t : I | psi t \\/ phi t} -> A t)\n    (e_psi : (t : psi) -> a t = b t)\n    (e_phi : (t : phi) -> a t = b t)\n    (border-is-a-set : {t : I | psi t /\\ phi t} -> isaset (A t))\n  : {t : I | psi t \\/ phi t} -> a t = b t\n  := recId r I psi phi\n        (\\t -> a t = b t)\n        e_psi e_phi\n        (\\t -> border-is-a-set t (a t) (b t) (e_psi t) (e_phi t))\n";
-
-      snippet_stlc = "#lang stlc\n\n#infer Ξ»A β†’ Ξ»x β†’ x\n    \n#infer Ξ»f β†’ f x y\n    \n#infer Ξ»f β†’ f f\n\n#infer Ξ»f β†’ Ξ»g β†’ Ξ»x β†’ f (g x)\n  \n#infer Ξ»f β†’ Ξ»g β†’ Ξ»x β†’ f g (g x)\n";
-
-      snippet_pcf = "#lang pcf\n\n-- infer the type of factorial\n#infer fix -- using fixpoint combinator to simulate recursion\n  (Ξ»fct β†’ Ξ»n β†’\n    if isZero n\n      then 1\n      else n * (fct (pred n)))\n\n-- compute 8!\n#whnf fix -- using fixpoint combinator to simulate recursion\n  (Ξ»fct β†’ Ξ»n β†’\n    if isZero n\n      then 1\n      else n * (fct (pred n)))\n  8\n\n";
-
-      snippet_mltt = "#lang mltt\n\n-- eta-expanded J\n#infer\n  Ξ»A β†’ Ξ»C β†’ Ξ»d β†’ Ξ»x β†’ Ξ»p β†’\n    J(A, a, C, d, x, p)\n\n-- path inversion\n#infer\n--  Ξ»A β†’ Ξ»x β†’ Ξ»y β†’\n  Ξ»p β†’\n  	J(A, x, Ξ»z β†’ Ξ»q β†’ z =_{A} x, refl(x), y, p)\n      \n-- path inversion of refl yields refl\n#nf\n  Ξ»A β†’ Ξ»a β†’\n  (Ξ»x β†’ Ξ»y β†’ Ξ»p β†’ J(A, x, Ξ»z β†’ Ξ»q β†’ z =_{A} x, refl(x), y, p))\n    a a (refl(a))\n\n-- concatenation of paths (transitivity)      \n#infer\n  Ξ»p β†’ Ξ»q β†’\n    J(A, y, Ξ»w β†’ Ξ»_s β†’ x =_{A} w, p, z, q)\n";
-
-      snippet = "";
-
-      /* use default snippet if one is not set in the query parameters */
-      if (params.has("snippet")) {
-        snippet = decodeURIComponent(params.get("snippet"));
-      } else if (params.has("snippet_url")) {
-        snippet_url = decodeURIComponent(params.get("snippet_url"));
-        fetch(snippet_url).then(function (response) {
-          // The API call was successful!
-          response.text().then(function(txt) {
-            snippet = txt;
-            myCodeMirror.setValue(snippet);
-          });
-        }).catch(function (err) {
-          // There was an error
-          console.warn('Something went wrong.', err);
-        });
-      }
-
-      if (!snippet) {
-          /* default lang is rzk-1 */
-          lang = "rzk-1";
-
-          if (params.has("lang")) {
-            lang = decodeURIComponent(params.get("lang"));
-          }
-
-          if (lang == "mltt")  { snippet = snippet_mltt; }
-          if (lang == "pcf")   { snippet = snippet_pcf; }
-          if (lang == "stlc")  { snippet = snippet_stlc; }
-          if (lang == "rzk-1") { snippet = snippet_rzk1; }
-          myCodeMirror.setValue(snippet);
-      }
-
-      myCodeMirror.setOption("extraKeys", {
-        "Ctrl-Enter": function(cm) {
-          __rzk__trigger_Check(myCodeMirror.getValue());
-        }
-      });
-    </script>
-  </body>
-</html>
diff --git a/try-rzk/result b/try-rzk/result
deleted file mode 120000
index 7852af3a6..000000000
--- a/try-rzk/result
+++ /dev/null
@@ -1 +0,0 @@
-/nix/store/ffp11s3gkqfisqb787rfl2v4vr06rpax-try-rzk-0.1.0
\ No newline at end of file