Merge pull request #711 from selfcustody/release-25.09.0
What changed, and why it matters
This commit is a routine release merge (Release 25.09.0) that adds the entire Krux project repository as a new import. The diff shows only new files: documentation, images, build tooling, CI workflows, configuration, and source code. There is no patch to existing code, no bug fix, and no security-relevant change described in the commit message or diff. It is a large content addition, not a vulnerability fix or security update.
No security action is required for this commit. Treat it as a normal release merge. If auditing the release, review the actual source code and prior commits in the release branch for security-relevant changes rather than this merge commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
Commit 8e4a2cfb64341505a035f3477277a84aaaf06025 is a merge of pull request #711 for ‘release-25.09.0’. The diff consists entirely of file additions (+3,144,733 bytes, 771 files) covering docs, assets, CI workflows, Docker build, lint configs, simulator, tests, firmware scripts, and source code. No deletions or modifications to existing files are present. The commit message and CHANGELOG describe feature additions and past security fixes, but the commit itself is a release merge with no direct code changes. No CVE, advisory, vendor security disclosure, or researcher attribution is present in the supplied materials.
Changed components
Inspect captured patch +3144733 / −0
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..1dc4f3d
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,2 @@
+[html]
+show_contexts = True
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..b39f302
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,24 @@
+---
+name: 🐞 Bug report
+about: Create a new report
+title: "[Bug] the summary of your report"
+labels: bug
+assignees: ''
+
+---
+
+#### Describe the bug
+<!-- Please try to be specific in providing all the steps to reproduce the error. -->
+
+**Device(s) affected**
+- [ ] Amigo
+- [ ] M5stickV
+- [ ] Cube
+- [ ] Dock
+- [ ] Bit
+- [ ] Yahboom
+- [ ] WonderMV
+
+**Version affected**
+- [ ] Official release (selfcustody/krux): vXX.YY.Z <!-- Specify the version! -->
+- [ ] Beta release (odudex/krux_binaries): vXX.YY.Z-betaWW <!-- Specify the version! -->
diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md
new file mode 100644
index 0000000..1d7efbc
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/enhancement.md
@@ -0,0 +1,10 @@
+---
+name: 🔥 Enhancement
+about: New feature request
+title: "[Enhancement] summarize the new feature or enhancement"
+labels: enhancement
+assignees: ''
+
+---
+
+#### Describe your request
diff --git a/.github/ISSUE_TEMPLATE/help_wanted.md b/.github/ISSUE_TEMPLATE/help_wanted.md
new file mode 100644
index 0000000..fe6e3f6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/help_wanted.md
@@ -0,0 +1,10 @@
+---
+name: 🥺 Other
+about: Anything not related to a bug or feature
+title: "[Other] summarize what is"
+labels: other
+assignees: ''
+
+---
+
+#### Describe what it is
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..97d9c1d
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,19 @@
+### What is this PR for?
+
+
+
+### Changes made to:
+- [ ] Code
+- [ ] Tests
+- [ ] Docs
+- [ ] CHANGELOG
+
+
+### Did you build the code and tested on device?
+- [ ] Yes, build and tested on <!-- device-name -->
+
+### What is the purpose of this pull request?
+- [ ] Bug fix
+- [ ] New feature
+- [ ] Docs update
+- [ ] Other
diff --git a/.github/codecov.yml b/.github/codecov.yml
new file mode 100644
index 0000000..8b56d53
--- /dev/null
+++ b/.github/codecov.yml
@@ -0,0 +1,10 @@
+coverage:
+ status:
+ project:
+ default:
+ target: 95%
+ threshold: 5%
+ patch:
+ default:
+ target: 95%
+ threshold: 5%
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..dd7f29d
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,215 @@
+name: Build
+
+on:
+ push:
+ branches:
+ - main
+ - develop
+ - 'release-**'
+
+jobs:
+ build:
+ strategy:
+ matrix:
+ device: [maixpy_m5stickv, maixpy_amigo, maixpy_bit, maixpy_dock, maixpy_yahboom, maixpy_cube, maixpy_wonder_mv]
+ runs-on: ubuntu-latest
+ services:
+ registry:
+ image: registry:2
+ ports:
+ - 5000:5000
+ steps:
+ - name: Remove unnecessary files
+ run: |
+ sudo rm -rf /usr/share/dotnet
+ sudo rm -rf /opt/ghc
+ sudo rm -rf "/usr/local/share/boost"
+ sudo rm -rf "$AGENT_TOOLSDIRECTORY"
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ with:
+ driver-opts: network=host
+ - name: Cache Docker layers
+ uses: actions/cache@v4
+ with:
+ path: /tmp/.buildx-cache
+ key: ${{ runner.os }}-buildx-${{ github.sha }}
+ restore-keys: |
+ ${{ runner.os }}-buildx-
+
+ - name: Build for M5StickV
+ if: matrix.device == 'maixpy_m5stickv'
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ build-args: DEVICE=maixpy_m5stickv
+ push: true
+ tags: localhost:5000/selfcustody/krux-builder-m5stickv:latest
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+ - name: Extract firmware for M5StickV
+ id: extract-m5stickv
+ if: matrix.device == 'maixpy_m5stickv'
+ uses: shrink/actions-docker-extract@v3
+ with:
+ image: localhost:5000/selfcustody/krux-builder-m5stickv:latest
+ path: /src/firmware/Kboot/build/.
+ - name: Upload firmware for M5StickV
+ if: matrix.device == 'maixpy_m5stickv'
+ uses: actions/upload-artifact@v4
+ with:
+ path: ${{ steps.extract-m5stickv.outputs.destination }}
+ name: build-m5stickv
+
+ - name: Build for Amigo
+ if: matrix.device == 'maixpy_amigo'
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ build-args: DEVICE=maixpy_amigo
+ push: true
+ tags: localhost:5000/selfcustody/krux-builder-amigo:latest
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+ - name: Extract firmware for Amigo
+ id: extract-amigo
+ if: matrix.device == 'maixpy_amigo'
+ uses: shrink/actions-docker-extract@v3
+ with:
+ image: localhost:5000/selfcustody/krux-builder-amigo:latest
+ path: /src/firmware/Kboot/build/.
+ - name: Upload firmware for Amigo
+ if: matrix.device == 'maixpy_amigo'
+ uses: actions/upload-artifact@v4
+ with:
+ path: ${{ steps.extract-amigo.outputs.destination }}
+ name: build-amigo
+
+ - name: Build for Bit
+ if: matrix.device == 'maixpy_bit'
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ build-args: DEVICE=maixpy_bit
+ push: true
+ tags: localhost:5000/selfcustody/krux-builder-bit:latest
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+ - name: Extract firmware for Bit
+ id: extract-bit
+ if: matrix.device == 'maixpy_bit'
+ uses: shrink/actions-docker-extract@v3
+ with:
+ image: localhost:5000/selfcustody/krux-builder-bit:latest
+ path: /src/firmware/Kboot/build/.
+ - name: Upload firmware for Bit
+ if: matrix.device == 'maixpy_bit'
+ uses: actions/upload-artifact@v4
+ with:
+ path: ${{ steps.extract-bit.outputs.destination }}
+ name: build-bit
+
+ - name: Build for Dock
+ if: matrix.device == 'maixpy_dock'
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ build-args: DEVICE=maixpy_dock
+ push: true
+ tags: localhost:5000/selfcustody/krux-builder-dock:latest
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+ - name: Extract firmware for Dock
+ id: extract-dock
+ if: matrix.device == 'maixpy_dock'
+ uses: shrink/actions-docker-extract@v3
+ with:
+ image: localhost:5000/selfcustody/krux-builder-dock:latest
+ path: /src/firmware/Kboot/build/.
+ - name: Upload firmware for Dock
+ if: matrix.device == 'maixpy_dock'
+ uses: actions/upload-artifact@v4
+ with:
+ path: ${{ steps.extract-dock.outputs.destination }}
+ name: build-dock
+
+ - name: Build for Yahboom
+ if: matrix.device == 'maixpy_yahboom'
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ build-args: DEVICE=maixpy_yahboom
+ push: true
+ tags: localhost:5000/selfcustody/krux-builder-yahboom:latest
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+ - name: Extract firmware for Yahboom
+ id: extract-yahboom
+ if: matrix.device == 'maixpy_yahboom'
+ uses: shrink/actions-docker-extract@v3
+ with:
+ image: localhost:5000/selfcustody/krux-builder-yahboom:latest
+ path: /src/firmware/Kboot/build/.
+ - name: Upload firmware for Yahboom
+ if: matrix.device == 'maixpy_yahboom'
+ uses: actions/upload-artifact@v4
+ with:
+ path: ${{ steps.extract-yahboom.outputs.destination }}
+ name: build-yahboom
+
+ - name: Build for Cube
+ if: matrix.device == 'maixpy_cube'
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ build-args: DEVICE=maixpy_cube
+ push: true
+ tags: localhost:5000/selfcustody/krux-builder-cube:latest
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+ - name: Extract firmware for Cube
+ id: extract-cube
+ if: matrix.device == 'maixpy_cube'
+ uses: shrink/actions-docker-extract@v3
+ with:
+ image: localhost:5000/selfcustody/krux-builder-cube:latest
+ path: /src/firmware/Kboot/build/.
+ - name: Upload firmware for Cube
+ if: matrix.device == 'maixpy_cube'
+ uses: actions/upload-artifact@v4
+ with:
+ path: ${{ steps.extract-cube.outputs.destination }}
+ name: build-cube
+
+ - name: Build for WonderMV
+ if: matrix.device == 'maixpy_wonder_mv'
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ build-args: DEVICE=maixpy_wonder_mv
+ push: true
+ tags: localhost:5000/selfcustody/krux-builder-wonder-mv:latest
+ cache-from: type=local,src=/tmp/.buildx-cache
+ cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
+ - name: Extract firmware for WonderMV
+ id: extract-wonder-mv
+ if: matrix.device == 'maixpy_wonder_mv'
+ uses: shrink/actions-docker-extract@v3
+ with:
+ image: localhost:5000/selfcustody/krux-builder-wonder-mv:latest
+ path: /src/firmware/Kboot/build/.
+ - name: Upload firmware for WonderMV
+ if: matrix.device == 'maixpy_wonder_mv'
+ uses: actions/upload-artifact@v4
+ with:
+ path: ${{ steps.extract-wonder-mv.outputs.destination }}
+ name: build-wonder-mv
+
+ - name: Move cache
+ run: |
+ rm -rf /tmp/.buildx-cache
+ mv /tmp/.buildx-cache-new /tmp/.buildx-cache
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000..0195873
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,31 @@
+name: Docs
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ build-gh-pages:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Install dependencies
+ run: |
+ python3 -m pip install --upgrade pip
+ python3 -m pip install poetry
+ - name: Install docs dependencies
+ run: poetry install --extras docs
+ - name: Build docs
+ run: poetry run mkdocs build
+ - name: Deploy
+ uses: peaceiris/actions-gh-pages@v4
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./public
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..4ed5edf
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,110 @@
+name: Tests
+
+on:
+ push:
+ branches:
+ - main
+ - develop
+ pull_request:
+
+jobs:
+ lint-black:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - uses: psf/black@stable
+ with:
+ options: "--check --verbose"
+ src: "./firmware/font"
+ - uses: psf/black@stable
+ with:
+ options: "--check --verbose"
+ src: "./firmware/scripts"
+ - uses: psf/black@stable
+ with:
+ options: "--check --verbose"
+ src: "./i18n"
+ - uses: psf/black@stable
+ with:
+ options: "--check --verbose"
+ src: "./src"
+ - uses: psf/black@stable
+ with:
+ options: "--check --verbose"
+ src: "./tests"
+
+ lint-pylint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Install dependencies
+ run: |
+ python3 -m pip install --upgrade pip
+ python3 -m pip install pylint
+ - name: Lint
+ run: |
+ pylint firmware/font/*.py
+ pylint firmware/scripts/*.py
+ pylint i18n/*.py
+ pylint src
+
+ check-translations:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Validate translations
+ run: cd i18n && python3 i18n.py validate
+
+ run-tests:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Install dependencies
+ run: |
+ python3 -m pip install --upgrade pip
+ python3 -m pip install poetry
+ - name: Install project and its dependencies
+ run: poetry install
+ - name: Run tests
+ run: poetry run pytest --cache-clear tests
+
+ coverage:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@main
+ with:
+ submodules: recursive
+ - name: Setup Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+ - name: Install dependencies
+ run: |
+ python3 -m pip install --upgrade pip
+ python3 -m pip install poetry
+ - name: Install project and its dependencies
+ run: poetry install
+ - name: Build coverage file
+ run: poetry run pytest --cache-clear --cov src/krux --cov-report xml tests
+ - name: Upload coverage reports to Codecov with GitHub Action
+ uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..02a62f2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,88 @@
+# Compiled Sources
+###################
+*.o
+*.a
+*.elf
+*.bin
+*.map
+*.hex
+*.kff
+*.dis
+*.exe
+
+# Packages
+############
+
+# Logs and Databases
+######################
+*.log
+
+# VIM Swap Files
+######################
+*.swp
+
+# Build directories
+######################
+build/
+build-*/
+
+# Test failure outputs
+######################
+tests/results/*
+
+# Python cache files
+######################
+__pycache__/
+.pytest_cache
+*.pyc
+*.egg-info
+
+# Customized Makefile/project overrides
+######################
+GNUmakefile
+user.props
+
+# Generated rst files
+######################
+genrst/
+
+# MacOS desktop metadata files
+######################
+.DS_Store
+
+.vagrant
+
+.config.mk
+.flash.conf.json
+in.txt
+out.txt
+sitemap.xml.gz
+*.bin
+*.bin.sig
+*.bin.sha256.txt
+*.kfpkg
+*.kfpkg.sig
+*.kfpkg.sha256.txt
+*.zip
+*.zip.sig
+*.zip.sha256.txt
+memzip-files.c
+memzip-files.zip
+.coverage
+.coverage.*
+privkey.pem
+pubkey.pem
+simulator/krux-screenshots
+simulator/screenshots
+simulator/sd
+simulator/flash
+
+# allow files: firmware.bin, .sig, .sha256.txt
+!tests/*
+!tests/files/*
+
+# ignore build-release files
+krux-*/ktool*
+
+# IDE files
+.vscode
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..9ff0259
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,15 @@
+[submodule "embit"]
+ path = vendor/embit
+ url = ../../diybitcoinhardware/embit
+[submodule "urtypes"]
+ path = vendor/urtypes
+ url = ../../selfcustody/urtypes
+[submodule "foundation-ur-py"]
+ path = vendor/foundation-ur-py
+ url = ../../selfcustody/foundation-ur-py
+[submodule "firmware/Kboot"]
+ path = firmware/Kboot
+ url = ../../selfcustody/Kboot
+[submodule "firmware/MaixPy"]
+ path = firmware/MaixPy
+ url = ../../selfcustody/MaixPy
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..b99a6ed
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,554 @@
+[MASTER]
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code.
+extension-pkg-whitelist=
+
+# Specify a score threshold to be exceeded before program exits with error.
+fail-under=10.0
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS,
+ .vagrant,
+ build,
+ embit,
+ foundation-ur-py,
+ MaixPy,
+ urtypes,
+ translations.py
+
+# Add files or directories matching the regex patterns to the blacklist. The
+# regex matches against base names, not paths.
+ignore-patterns=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
+# number of processors available to use.
+jobs=1
+
+# Control the amount of potential inferred values when inferring a single
+# object. This can help the performance when dealing with large functions or
+# complex, nested conditions.
+limit-inference-results=100
+
+# List of plugins (as comma separated values of python module names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# When enabled, pylint would attempt to guess common misconfiguration and emit
+# user-friendly hints instead of false-positive error messages.
+suggestion-mode=yes
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
+confidence=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once). You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use "--disable=all --enable=classes
+# --disable=W".
+disable=bad-inline-option,
+ locally-disabled,
+ file-ignored,
+ suppressed-message,
+ useless-suppression,
+ deprecated-pragma,
+ use-symbolic-message-instead,
+ bare-except,
+ broad-except,
+ consider-using-f-string,
+ missing-module-docstring,
+ import-error,
+ consider-using-with,
+ consider-using-enumerate,
+ unspecified-encoding,
+ exec-used,
+ import-outside-toplevel,
+ wrong-import-position,
+ wrong-import-order,
+ duplicate-code,
+ ungrouped-imports,
+ raise-missing-from,
+ anomalous-backslash-in-string,
+ too-many-positional-arguments # Todo: remove this and adapt for releases above 24.09.0
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=c-extension-no-member
+
+
+[REPORTS]
+
+# Python expression which should return a score less than or equal to 10. You
+# have access to the variables 'error', 'warning', 'refactor', and 'convention'
+# which contain the number of messages in each category, as well as 'statement'
+# which is the total number of statements analyzed. This score is used by the
+# global evaluation report (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details.
+#msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio). You can also give a reporter class, e.g.
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Tells whether to display a full report or only the messages.
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=6
+
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=sys.exit
+
+
+[LOGGING]
+
+# The type of string formatting that logging methods do. `old` means using %
+# formatting, `new` is for `{}` formatting.
+logging-format-style=old
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format.
+logging-modules=logging
+
+
+[SPELLING]
+
+# Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
+
+# Spelling dictionary name. Available dictionaries: none. To make it work,
+# install the python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains the private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to the private dictionary (see the
+# --spelling-private-dict-file option) instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,
+ XXX
+
+# Regular expression of note tags to take in consideration.
+#notes-rgx=
+
+
+[TYPECHECK]
+
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=sleep_ms,
+ ticks_ms,
+ print_exception
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# Tells whether to warn about missing members when the owner of the attribute
+# is inferred to be None.
+ignore-none=yes
+
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis). It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
+
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
+
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+# List of decorators that change the signature of a decorated function.
+signature-mutators=
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid defining new builtins when possible.
+additional-builtins=const
+
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,
+ _cb
+
+# A regular expression matching the name of dummy variables (i.e. expected to
+# not be used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore.
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
+
+
+[FORMAT]
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Maximum number of lines in a module.
+max-module-lines=1200
+
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+
+[SIMILARITIES]
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[BASIC]
+
+# Naming style matching correct argument names.
+argument-naming-style=snake_case
+
+# Regular expression matching correct argument names. Overrides argument-
+# naming-style.
+#argument-rgx=
+
+# Naming style matching correct attribute names.
+attr-naming-style=snake_case
+
+# Regular expression matching correct attribute names. Overrides attr-naming-
+# style.
+#attr-rgx=
+
+# Bad variable names which should always be refused, separated by a comma.
+bad-names=foo,
+ bar,
+ baz,
+ toto,
+ tutu,
+ tata
+
+# Bad variable names regexes, separated by a comma. If names match any regex,
+# they will always be refused
+bad-names-rgxs=
+
+# Naming style matching correct class attribute names.
+class-attribute-naming-style=any
+
+# Regular expression matching correct class attribute names. Overrides class-
+# attribute-naming-style.
+#class-attribute-rgx=
+
+# Naming style matching correct class names.
+class-naming-style=PascalCase
+
+# Regular expression matching correct class names. Overrides class-naming-
+# style.
+#class-rgx=
+
+# Naming style matching correct constant names.
+const-naming-style=UPPER_CASE
+
+# Regular expression matching correct constant names. Overrides const-naming-
+# style.
+#const-rgx=
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+# Naming style matching correct function names.
+function-naming-style=snake_case
+
+# Regular expression matching correct function names. Overrides function-
+# naming-style.
+#function-rgx=
+
+# Good variable names which should always be accepted, separated by a comma.
+good-names=i,
+ j,
+ k,
+ x,
+ y,
+ z,
+ m,
+ n,
+ s,
+ v,
+ d,
+ e,
+ t,
+ ex,
+ sc,
+ tx,
+ Run,
+ firmware_hash,
+ sd,
+ f,
+ mv,
+ size_KB,
+ size_KB_fraction,
+ sd_total_MB,
+ sd_free_MB,
+ _
+
+# Good variable names regexes, separated by a comma. If names match any regex,
+# they will always be accepted
+good-names-rgxs=
+
+# Include a hint for the correct naming format with invalid-name.
+include-naming-hint=no
+
+# Naming style matching correct inline iteration names.
+inlinevar-naming-style=any
+
+# Regular expression matching correct inline iteration names. Overrides
+# inlinevar-naming-style.
+#inlinevar-rgx=
+
+# Naming style matching correct method names.
+method-naming-style=snake_case
+
+# Regular expression matching correct method names. Overrides method-naming-
+# style.
+#method-rgx=
+
+# Naming style matching correct module names.
+module-naming-style=snake_case
+
+# Regular expression matching correct module names. Overrides module-naming-
+# style.
+#module-rgx=
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# List of decorators that produce properties, such as abc.abstractproperty. Add
+# to this list to register other decorators that produce valid properties.
+# These decorators are taken in consideration only for invalid-name.
+property-classes=abc.abstractproperty
+
+# Naming style matching correct variable names.
+variable-naming-style=snake_case
+
+# Regular expression matching correct variable names. Overrides variable-
+# naming-style.
+#variable-rgx=
+
+
+[STRING]
+
+# This flag controls whether inconsistent-quotes generates a warning when the
+# character used as a quote delimiter is used inconsistently within a module.
+check-quote-consistency=no
+
+# This flag controls whether the implicit-str-concat should generate a warning
+# on implicit string concatenation in sequences defined over several lines.
+check-str-concat-over-line-jumps=no
+
+
+[IMPORTS]
+
+# List of modules that can be imported at any level, not just the top level
+# one.
+allow-any-import-level=
+
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
+
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Deprecated modules which should not be used, separated by a comma.
+deprecated-modules=optparse,tkinter.tix
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled).
+ext-import-graph=
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled).
+import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled).
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+# Couples of modules and preferred modules, separated by a comma.
+preferred-modules=
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,
+ __new__,
+ setUp,
+ __post_init__
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,
+ _fields,
+ _replace,
+ _source,
+ _make
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=cls
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method.
+max-args=10
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=11
+
+# Maximum number of boolean expressions in an if statement (see R0916).
+max-bool-expr=5
+
+# Maximum number of branch for function / method body.
+max-branches=22
+
+# Maximum number of locals for function / method body.
+max-locals=26
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=30
+
+# Maximum number of return / yield for function / method body.
+max-returns=11
+
+# Maximum number of statements in function / method body.
+max-statements=81
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=0
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..76b3429
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,567 @@
+# Changelog 25.09.0 - September 2025
+
+### Extended Encryption Options
+The KEF encryption format now supports additional modes (CTR and the new default, GCM) and can hide strings of arbitrary length. This enables secure handling of passphrases, wallet descriptors, PSBTs, addresses, and other messages.
+
+### Datum Tool
+A new advanced utility for working with files, QR codes, and manual text input. It supports:
+- Conversion between binary and common string encodings
+- Encryption/decryption of KEF envelopes
+- Exporting contents to QR or SD
+
+### 2x Faster TC Flash Hash and Key Stretching
+SHA-256 and PBKDF2-HMAC now use hardware-accelerated hashing, doubling the speed of TC Flash Hash tampering detection tool, encryption, and decryption.
+
+### SD Card Airgapped Firmware Upgrade Optimizations
+- Verifies firmware signature authenticity before prompting for update
+- Ensures only compatible firmware can be installed
+- Displays the firmware version being installed for confirmation
+- Hardware-accelerated SHA-256 hashing and other optimizations speed up checks
+
+### Support for "Old" Multisig Policies and Scripts
+We added support for BIP45 (Legacy multisig `P2SH`) and complete BIP48 (Nested-Segwit `P2SH-P2WSH`).
+
+### Button Turbo
+Hold the NEXT or PREVIOUS button to move faster through menus and other keypads (Tinyseed, Stackbit, Mnemonic Editor, Show Datum).
+
+### 'New Mnemonic' Menu Disabled with 'Hide Mnemonic'
+When 'Hide Mnemonic' setting is enabled, the 'New Mnemonic' menu is automatically disabled.
+
+### Improved Text Highlighting
+Wallet fingerprint, network, keypad titles, settings categories, and prefix texts are now highlighted across all screens.
+
+### Enhanced Settings Category Colors
+Boolean settings (True/False) are now displayed with color (Green/Red) for improved visibility.
+
+### Enhanced Address Verification
+To facilitate comparison, addresses are displayed in space-separated groups of 4 characters with alternating colors.
+
+### Export Wallet Addresses
+Export *receive or change* addresses to a CSV file on the SD card.
+
+### New CNC Printer Support and Fixes (OpenBuilds GRBL 1.1)
+- Fixed CNC/FilePrinter compatibility with optimized QR codes from v24.0.3.0
+- Introduced CNC/GRBLPrinter for direct serial printing to CNC machines
+- Added support to choose between router/laser head engravers
+
+### Export QR Codes as SVG
+Exported QR codes can now be saved as SVG images.
+
+### Improved Tests
+- Code coverage: 10,000+ lines (96%) with 680+ tests, improving stability and reliability
+- Added in-device tests focusing on hardware-accelerated features in Tools
+
+### Other Bug Fixes and Improvements
+- Numbers are no longer printed as words in "Backup Mnemonic > Other formats > Numbers"
+- Expanded keypad touch area to screen edges
+- Tools > Print Test QR now asks for confirmation before printing
+- Tools > Check SD Card now allows deleting files
+- Load mnemonic > Via Manual Input > Word Numbers now shows the double mnemonic indicator (*) if applicable
+- Added fingerprint to mnemonic preview and editor
+- Fingerprint preview shown when changing wallet passphrase
+- Passphrase and key entry now display length to reduce mistakes
+- Saving encrypted mnemonic prompts to use fingerprint as ID
+- Optimized board value checks
+- Ellipsis now use a single character to save space
+- Added QR code to About screen
+- Fixed camera zoom mode clearing the QR progress bar
+- Fixed camera orientation, when settings changed on Yahboom and WonderMV without requiring reboot
+- Theme restart prompt appears only when changes are made
+- Wallet Descriptor validation now warns if change addresses cannot be determined
+- Wallet customization prompt now warns about descriptor unloading when something is changed
+- Fixed long wallet derivation path displaying issues
+- Added PSBT Review Again button to sign menu for verifying details muiltiple times without reloading the PSBT
+- Added confirmation prompt before exiting after showing signed PSBT QR code
+- Sign message now supports all binary file types
+- Change Addresses menu hidden when descriptor cannot provide them
+- List Addresses now allows swiping up or down to navigate to move between pages
+- Hide Mnemonic now skips confirmation when loading via word numbers
+- Text improvements for clarity and easier translation
+- Fixed mixed ASCII/Asian fonts not using full display width
+- Fixed menu entries cut off when translations span two lines
+- Fixed entry update bug when switching between PAGE and swipe in large menus
+- MaixPy Fix: Increased glyph indexing capacity for Amigo translations
+- Fixed issue allowing incompatible script types from policies in Default Wallet settings
+
+
+# Changelog 25.03.0 - March 2025
+
+### Taproot and WSH Miniscript support
+
+- Provides an indented visualization of Miniscript descriptor for easier inspection.
+- Includes policy and cosigner verification.
+- Supports custom derivations.
+- Detects unspendable internal keys in Taproot.
+- Contains several UI and settings modifications.
+
+### Easter Eggs Reveal
+Hints were added to unveil hidden features, such as swiping sideways to change the keypad keyset, switching camera modes, and adjusting QR code brightness.
+
+### Rearranged Keypad Keysets
+Keypad keysets were organized to group similar keys and help with visibility. Also the *"ABC"* key now changes to *"123"*, *"<>."* and *"abc"* according to the next keyset.
+
+### More Camera Modes
+A zoomed camera mode is available for all cameras, and an anti-glare mode has been added to the GC0328 camera.
+
+### More Intuitive Tamper Check
+The Tamper Check Flash Hash now appears immediately after the Tamper Check code is created, clarifying its purpose and expected output.
+
+### Display Customization Options
+Display orientation on Yahboom and WonderMV devices can now be flipped.
+
+### SD Card PSBT Signing Preserves All Fields
+When signing via SD cards, all fields in a PSBT—including signatures from other keys—are preserved. This facilitates workflows across multiple devices and locations by allowing a single PSBT file to be sequentially signed by different devices.
+
+### Other Bug Fixes and Optimizations
+- New encrypted mnemonics show key-strength score during confirmation. If stored, will be sorted alphabetically.
+- Flash Map drawing errors have been corrected.
+- Address scanning for Blue Wallet has been fixed following its export format change.
+- The use of “h” to indicate hardened derivation path nodes has been standardized.
+- A faster algorithm for double mnemonic calculation has been introduced.
+- PSBT change detection has been made more restrictive.
+
+
+# Changelog 24.11.1 - November 2024
+
+### Security Fix
+This release addresses a vulnerability affecting AES-CBC encrypted mnemonics stored on flash storage, SD cards, and QR codes. Due to an implementation error, the Initialization Vector (IV) in our CBC encryption, which used camera-generated entropy, was not being correctly utilized, which meant it did not provide the intended additional entropy.
+
+
+# Changelog 24.11.0 - November 2024
+
+### Tamper Check Flash Hash and Tamper Check Code (Experimental)
+The *Tamper Check Flash Hash* (TC Flash Hash) feature verifies the integrity of the device's flash memory by generating a unique tamper indicator that relies on hash properties. After setting up a *Tamper Check Code* (TC Code), this check can be performed at every boot or manually via `Tools -> Flash Tools`. The TC Code is a key component, required to execute the verification and detect unauthorized changes to the device's memory. Users can also fill unused memory blocks with camera-generated entropy to further mitigate tampering attempts.
+
+### Flash Map
+*Flash Map* is an auxiliary tool that allows users to visualize the regions of the device's memory that are empty. This helps users verify the results of actions such as:
+
+- Wiping the device's memory
+- Erasing the user's area
+- Saving settings and encrypted mnemonics
+- Filling empty blocks with camera-generated entropy
+
+### Japanese Translation
+Japanese translation has been added.
+
+### BIP85: Allow Export Base64 Passwords
+In addition to BIP39 Mnemonics, users can now derive Base64 passwords from their keys. These passwords, which can be used in standard logins, can be noted down, saved to an SD card, or exported as a QR code.
+
+### Vulnerability Fix: Block Import of Python Modules from SD Card
+A feature of MicroPython, commonly used for general-purpose development, is the ability to run Python code directly from an SD card. However, with the recent implementation of tamper detection tools, this behavior is now considered a vulnerability. It was discovered that MicroPython would prioritize importing `.pyc` (Python frozen modules) from an SD card before checking the internal flash, which could be exploited to run unintended code from the SD card. To address this, a block has been implemented in MicroPython to prevent running any code from the SD card, enhancing the overall security of the device.
+
+### Add Compatibility to Partial Text Mnemonic QR Codes
+Partial Text Mnemonic QR Codes, like Coldcard's backups, where mnemonics words are cropped and contain only the first 3 or 4 letters, are now auto-completed and loaded.
+
+### Multi-keypad Position Indicator
+An indicator has been added to the bottom of keypads to help users identify the keypad index while swiping between them.
+
+### WonderMV Simulator
+Computer simulator for WonderMV device has been added.
+
+### Krux Ethos
+Guidelines have been created to assist with decision-making regarding the Krux project's interactions with contributors, users, and businesses that may create products or services related to Krux.
+
+### Minor Bugfixes and Refactors
+Several code improvements for better reliability and efficiency.
+
+
+# Changelog 24.09.1 - September 26, 2024
+
+### Fix Camera Orientation on Cube
+Fix for the camera, that was being started upside-down on Maix Cube devices
+
+
+# Changelog 24.09.0 - September 25, 2024
+
+### New Device Support: WonderMV
+Manufactured by HiWonder, the WonderMV is similar to Yahboom K210 Module, with a few differences, including a metal enclosure, USB-C port, and screen backlight control.
+
+### Added Support for East Asian Languages - Korean and Simplified Chinese
+After implementing low-level support for different glyph form factors, we were finally able to introduce the long-awaited Korean language translation. Simplified Chinese support followed shortly thereafter.
+
+### Faster PSBT Scanning
+Reduced the time required to scan larger PSBTs by optimizing processing speed.
+
+### Improved QR Code Scanning
+Enhanced scan success rates in challenging conditions, such as reduced focus or scanning from greater distances.
+
+### UI Standardization
+The positions of "Yes" and "No" in prompts have been inverted to standardize the UI. Affirmative actions, such as "Yes," "Go," and "Proceed," will now be positioned on the right, while "No," "Esc," and "Back" will be on the left.
+
+### Enhanced Scanning Progress Bars
+QR code progress bars now provide more detailed information. For UR PSBTs, the progress bar indicates when a valid frame is captured, while for BBQR, it displays the index or position of the last successfully scanned frame.
+
+### Mnemoniocs Editor - Loading Mnemonics
+When manually loading an existing mnemonic, you can now correct typos and mistakes during the review stage by simply tapping or navigating to the incorrect words. The checksum word will be highlighted in red if the entered mnemonic is invalid to help detect eventual problems.
+
+### Mnemonics Editor - New Mnemonic
+When generating new mnemonics through dice rolls or camera images, you can now modify the entropy by changing some of the mnemonic words. The final word will dynamically adjust to always produce a valid checksum.
+
+### Support for Scanning Various Binary Grid Formats
+In addition to TinySeed, the camera can now scan and load mnemonics from equivalent formats, such as OneKey KeyTag, or even generic binary grids, like spreadsheets with colored, squared cells.
+
+### Message Signing Using SD cards
+Recently released in Sparrow, the SD card message signing workflow is now supported.
+
+### Generate Double Mnemonics from Camera
+When generating a new mnemonic using the camera, users can now choose to create a "Double Mnemonic," in addition to the standard 12 and 24-word options. This feature generates a 24-word mnemonic that, when split in half, forms two valid 12-word mnemonics.
+
+### Increased Valid Touch Surface
+To improve touch accuracy, especially on small touchscreens, the touch surface area of buttons has been increased to make better use of the available screen space.
+
+### Add Account Descriptor Type Support
+Krux now accepts urtype.Account type QR code descriptors.
+
+### Enhanced File Exploring
+File explorer now better differentiate files from folders.
+
+### Camera Adjustments for Yahboom and WonderMV
+Sensitivity and exposure adjustments were made to the GC2145 sensor, enhancing the scanning success rate for Yahboom and WonderMV devices.
+
+### About Shows Board Type
+Ensure you flashed the correct firmware for your device consulting the "About" menu item.
+
+### Simplified Translations
+Messages and terms were simplified to reduce firmware size and maintenance.
+
+### Bugfix - Signing Messages with ":" Character
+Fixed an issue where signing messages containing the ":" character would result in invalid signatures when signing at addresses.
+
+### Bugfix - Import of Base64 Encoded PSBTs from SD Card
+Fixed an issue where base64 encoded PSBTs imported from an SD card were not correctly detected and parsed.
+
+### Translation Removed: Polish
+Polish translation was removed due to the lack of maintainers and known users.
+
+### Code Refactor and Optimizations
+Several optimizations to increase performance and code quality.
+
+
+# Changelog 24.07.0 - July 15, 2024
+
+### Maix Cube Support
+The Maix Cube now has its first official release. This affordable and compact cube-shaped device, equipped with a built-in battery, is an excellent choice for those seeking a discreet option.
+
+### Frozen Code - Speed and Security Improvement
+Krux now runs cross-compiled (frozen) Python code instead of real-time compiled code. The Python real-time compiler and REPL have been disabled.
+
+### More Single-sig Script Types Support
+Beyond Native Segwit, users can now load Legacy, Nested Segwit, and Taproot script type wallets.
+
+### Accounts Support
+Users can now use custom account derivation indexes.
+
+### Wallet Customization Options
+New workflow to load wallets, faster for default settings and with more options when custom settings are needed. Wallet's network, script type, single/multisig, and account can be changed during and after loading a wallet.
+
+### BIP85 Support
+Generate, export, and load BIP85 child mnemonics.
+
+### Wallet Sans Key
+Krux now has a tool to load a trusted wallet descriptor to view addresses without the need for private keys.
+
+### Add BBQr Support
+Scan and export PSBTs and wallet descriptors in the compact and efficient BBQr format.
+
+### Update Embit
+Embit updated to 0.8.
+
+### Auto Shutdown - Security and Battery Saving Feature
+The device will automatically shut down at a configurable time if left on.
+
+### Hide Mnemonics - Security Feature
+Disable backup tools and hide private key data when a wallet is loaded.
+
+### PSBT Path Mismatch
+Detect and warn the user if the PSBT path differs from the loaded wallet's path. This is useful for users who use multiple script types with the same key, ensuring they use the correct account when sending transactions.
+
+### Show Multisig PSBT Policy When Descriptor is Not Loaded
+Ensure you are signing for the correct multisig setup by inspecting PSBT's fingerprints if the wallet descriptor is not loaded. If the descriptor is loaded, verification is done by Krux.
+
+### Status Bar Shows Loaded Fingerprint
+The loaded key's fingerprint is now shown in the status bar.
+
+### Fee Percentage of Transaction
+Show the transaction's fee as a proportion of the transaction cost, warning if it is greater than 10%.
+
+### Sats/vB
+PSBT now displays an accurate estimation of the transaction’s feerate.
+
+### Brightness Control for Maix Cube and M5stickV
+Adjust backlight intensity for better viewing and scanning from your Cube or M5stickV.
+
+### Fast Forward for Buttons
+Hold the NEXT or PREVIOUS buttons when navigating among letters while typing text to fast forward or backward.
+
+### Add Display Settings for Maix Amigo
+Add more display settings for Amigo to allow different display models to work properly.
+
+### Faster Address Scanning and Exploring
+The time to scan or display wallet addresses is now less than half compared to the previous version.
+
+### Sign PSBTs Without Fingerprints
+Krux will now sign PSBTs even if a fingerprint is not properly set on the coordinator. Krux will still warn the user to set it correctly or use Krux-exported public keys to set their coordinators.
+
+### Dice Rolls Pattern Detection
+Krux warns the user if it suspects there are patterns within the actual rolls
+
+### Optimized SD Card Signing
+Better suited for large transactions, SD card signing is now more RAM efficient, allowing transactions with +100 inputs to be signed in less than a minute.
+
+### Stand Alone Verifiable Signed PSBTs
+As required in BIP174, signed PSBT QR codes and SD card files now contain all the required data to verify the signatures without needing the original, unsigned PSBT.
+
+### Camera Optimizations for Yahboom (ver:1.1) With GC2145 Camera
+Recent Yahboom K210 devices (ver:1.1) come with the GC2145 camera instead of the OV2640 (ver:1.0). Optimizations and features, such as anti-glare, have been added for the new camera.
+
+### Yahboom and Cube Devices Added to Simulator
+Simulator can now run as M5stickV, Amigo, Dock, Yahboom, and Cube.
+
+### Files sorted in SD file explorer
+The SD file explorer now sorts files in ascending order, showing directories first.
+
+### Receive or change address now starts with the index 0
+Address explorer now shows receive and change address starting at index 0 instead of number 1.
+
+### Other Small Fixes and Code Optimizations
+Bugfixes, optimizations and code refactoring.
+
+
+# Changelog 24.03.0 - March 12, 2024
+
+## Changes
+
+### Wipe Device
+Option on tools to wipe the device, permanently removing settings and stored encrypted mnemonics by erasing every single bit of user's flash space.
+
+### Better Deletion of Mnemonics Stored on SD card
+When deleting an encrypted mnemonic from an SD card, Krux will now overwrite the memory area making it impossible to recover the previously stored data.
+
+### Save and Load Wallet Output Descriptor from SD card
+Create or load from a wallet output descriptor file on an SD card. The backup file format is compatible with most coordinators.
+
+### Sign Messages at a Derived Bitcoin address
+Sign messages from Sparrow and Specter, via QR code, also attesting a Bitcoin address belongs to you.
+
+### Reproducible Builds
+To enhance the reproducibility of firmware builds, random variables such as file write timestamps have been removed from the build process. As a result, builds from developers' computers, those built within GitHub Actions from published code, and those you compile locally are more likely to be identical and have the same hash checksum as the official and beta releases. This change ensures greater consistency and traceability across all builds.
+
+### Add Entropy Quality Estimation for Mnemonic Creation.
+Entropy quality estimators, like Shannon's entropy, were added to mnemonic generation through dice rolls and camera snapshot.
+
+### IRQ Interfaces
+Button and touch presses are now detected by the application through IO interrupts. Meaning inputs events will be registered and handled even if they happened when other tasks were being executed by the processor, resulting in a better UX.
+
+### Restore Default Settings
+Option to restore the device's settings to its factory state.
+
+### Optimized Settings Storage
+Device's storage is now used more efficiently, data is stored less frequently, only in case a setting is changed from defaults.
+
+### Amigo's Power Manager Enhancements
+The power management behavior for the Amigo device has been standardized. Previously, some devices would not wake up from shutdown or sleep mode. Now, these devices will fully shut down when the shutdown option is selected from the menu, and they will always power on when the power button is pressed for 1 second.
+
+### GUI Enhancements
+Icons, information text boxes, and rounded shapes are now present at the GUI.
+
+### Mnemonic Numbers
+To match the input options, export mnemonics as decimal, hexadecimal, or octal numbers. When loading from numbers, a new numbers confirmation screen was added.
+
+### Optimized QR codes
+QR codes rendering is faster and uses less RAM.
+
+### Export QR Codes as Images to SD Card
+Some QR codes can be exported as images to SD card.
+
+### Screensaver
+Optional screensaver to reduce pixels' burn-in and grab the attention of the user when the device is left powered on.
+
+### Addresses Exploring
+More receive and change addresses per page are shown on bigger screens.
+
+### Update Embit to version 0.7
+Use the latest Embit release.
+
+### Maix Dock Simulator
+Now Krux PC simulator can also run in Maix Dock mode, mimicking appearance and characteristics of the most DIY Krux device.
+
+### New Compatible Device - Yahboom
+The Yahboom Aimotion K210 module, a compact touchscreen device, now has its first official firmware release.
+
+### Join Amigo IPS and Amigo TFT firmwares
+Users will be able to flash a single firmware and change display settings if their device was shipped with a display different from standard TFT.
+
+### Other Small Fixes and Code Optimizations
+Many other small fixes and optimizations under the hood.
+
+
+# Version 23.09.1 - November 18, 2023
+This release contain bugfixes:
+
+Encrypted Mnemonic QR codes would fail to decrypt if PBKDF2 iterations settings was changed to non multiple of 10,000.
+
+QR code transcription helpers that highlight regions could crash on edges of some QR code sizes.
+
+Address navigation "previous" menu option wouldn't show correct number.
+
+
+# Version 23.09.0 - September 12, 2023
+After a long year, new features are finally coming out of beta and making their way into a stable release. Also @jreesun appointed @odudex as the new lead maintainer of the project.
+
+## Changes
+
+### Battery Indicator
+Check battery status of M5stickV or Maix Amigo on top right of the screen.
+
+### New Mnemonic From Camera
+Use camera as a source of entropy to quickly create a mnemonic.
+
+### Tiny Seed - Export, Print, Punch, Manually Load or Scan
+Import and export a binary representation of your mnemonic, in a format popularized by Tiny Seed metal plates. BIP39 mnemonic words number, ranging from 1 to 2048 are punched in binary format on a rectangular grid.
+Krux will automatically convert a mnemonic to Tiny Seed format allowing to print or transcript it. You can also load a tiny seed toggling word bits on screen, or make use of machine vision capabilities of K210 chip to directly scan a Tiny Seed mnemonic backup stored on metal or paper.
+
+### Stackbit - Import and Export
+Without needing tools, guides or dictionaries, import and export another metal plate backup format, where each of the four digits of the word's number is a sum of marked (punched) numbers 1,2,4 and 8.
+
+### Enter Mnemonic as Word Numbers - Hex and Octal formats
+Also available in some metal plate backup formats, you could load your mnemonic words from its decimal BIP39 word number (1-2048), now you can also load from its hexadecimal(0x1-0x800) or octal(01-04000) word number.
+
+### Encryption and Storage
+Conveniently store your mnemonics on device's internal flash memory or removable SD card, protecting them with encryption. It is now possible to export encrypted QR codes too.
+
+### Addresses
+Beyond verifying your wallet's receive addresses, you can now also list, export and print receive and change addresses.
+
+### SD Card Hot plugging
+SD cards can now be inserted and removed at any time, making it easier to use it for signing transactions, messages and storing encrypted mnemonics.
+
+### Transcript Tools for QR codes
+Different visualization modes which make it easier to transcript QR codes.
+
+### Transaction Details
+When signing a transaction, more information is presented, ensuring that the user sees all details before signing.
+
+### Tools
+#### Check SD Card
+Check if the SD card is detected and explore its content.
+
+#### Delete Mnemonic
+Delete any stored encrypted mnemonic, on device's internal flash memory or SD card.
+
+#### Print Test QR
+Quickly print a test QR code to check and optimize your printer setup.
+
+#### Create QR Code
+Enter a text input to create, print or transcript a QR code that can be later used as an encryption key or as a passphrase.
+
+### Themes
+Choose your color theme according to your preference.
+
+### Thermal Printing and CNC
+More mnemonic export formats and tools to create and print generic QR codes to be used as passphrases or encryption keys. You can also export QR codes to gcode files and save them in SD cards, allowing you to machine them GRBL compatible CNCs without the need of computers and CAD tools.
+
+### More Settings
+#### Persist
+Choose where you want to store your settings, on internal flash memory or SD card.
+
+#### Touchscreen
+If your device has touchscreen you can change the touch detection threshold.
+
+### Languages
+Dutch translations were added.
+
+### UI Tweaks
+Small changes to optimize user experience.
+
+### Under the Hood
+Small bugfixes, optimizations and code refactoring, targeting better compatibility with coordinator softwares, faster boot and better RAM management.
+
+
+# Version 22.08.2 - September 13, 2022
+
+This patch release reverts the zpub QR code format, once again including key origin derivation info which is necessary for BlueWallet to use when preparing PSBTs for signing with single-key wallets.
+
+It is recommended to update to this version if you are using a single-key "Imported Watch-only" wallet with BlueWallet and are seeing a "cannot sign" error message when trying to send an outgoing transaction. If so, please do the following:
+
+1. Upgrade Krux to this new release
+2. Delete the affected wallet in BlueWallet (funds are safu as long as you have your mnemonic)
+3. Create a new wallet in BlueWallet by importing from the new zpub QR code that Krux now displays.
+4. Open the wallet in BlueWallet and pull down to fetch the old wallet's transaction history.
+5. Create a new outgoing transaction and scan the QR code with Krux.
+6. Krux should display the tx information and allow you to sign.
+7. Display the signed QR back to BlueWallet.
+8. Broadcast!
+
+
+# Version 22.08.1 - August 11, 2022
+
+This release is to fix a bug that would have prevented Amigos from performing airgapped upgrades to the next release.
+
+
+# Version 22.08.0 - August 10, 2022
+
+This latest version of Krux is brought to you by @odudex, who tirelessly worked for months to get Krux working on three new devices: the Maix Amigo, Maix Bit, and Maix Dock. Thank you for all your hard work!
+
+Many other improvements to Krux were made along the way which will be listed below.
+
+Enjoy!
+
+## Installing
+For instructions on how to install this release, please follow the *Getting Started* guide on [https://selfcustody.github.io/krux/](https://selfcustody.github.io/krux/).
+
+To perform an airgapped upgrade (with a microSD card) from a previous signed release, please follow the directions here: [https://selfcustody.github.io/krux/getting-started/installing/#upgrade-via-microsd-card](https://selfcustody.github.io/krux/getting-started/installing/#upgrade-via-microsd-card)
+
+## Changes
+### ¡Three Amigos!
+Krux now supports three new devices: Maix Amigo, Maix Bit, and Maix Dock. The Amigo is an all-in-one device with a touchscreen display, while the Dock and Bit are more DIY-focused kits where some assembly is required.
+
+### New touchscreen UI + UX enhancements
+Along with being usable on multiple devices now, Krux also has native touchscreen support and many refinements to its UI to make better use of the screen space it has. More work has gone into improving UX including the ability to escape out of the mnemonic loading or creation screens at any point.
+
+### Built-in translations + Portuguese
+Krux now includes translations in the firmware due to using a more space-efficient font format. With this change, the rendering issues with Vietnamese characters have also been fixed. A new Portuguese translation has been added.
+
+### Amigo support added to Krux Simulator
+The Krux Simulator, which lets you simulate on your PC what it would be like to run Krux on a device, was updated to support the Amigo. There is also now a PC option if you want to run Krux "natively" on your PC (**NOTE**: This is a toy for fun and is *not recommended* for real usage).
+
+### CompactSeedQR support
+Support for scanning SeedSigner’s newer "CompactSeedQR" QR codes
+
+### BIP39 passphrases
+Support has been added for BIP39 passphrases. After loading a mnemonic, you will be asked if you want to "Add a passphrase?" to it.
+
+### Export signed PSBTs to microSD
+You can now save a signed PSBT to microSD which should help users having trouble getting their webcams to read the tiny QR codes on the M5StickV. Furthermore, Krux supports loading a PSBT from microSD as well if you want to forgo QR codes entirely.
+
+### Better mnemonic generation
+The flow for entering rolls has been streamlined to allow more rapid input, with your string of rolls now being visible along the top of the screen as you go. We also introduced a change to how the D6 roll string is built, no longer including "-" between rolls prior to hashing to have consistency with ColdCard and SeedSigner.
+
+Note: We continue to use a "-" separator between D20 rolls to avoid reducing state space due to collisions (e.g., rolling 1-17 and 11-7 would result in the same 117 string without a separator, and would thus have the same hash)
+
+### Back button and rotary encoders
+All devices, even the M5StickV, support moving backward in the UI now. The left-side power button on the M5StickV no longer does one-press resets and instead acts as a third input button. Note: You can still shutdown the device by holding it down for 5 seconds.
+
+Support for using a rotary encoder as the previous and next buttons has also been added. Check out @odudex’s open source case design with instructions on how to use one with the Dock:
+[https://github.com/odudex/DockEncoderCase](https://github.com/odudex/DockEncoderCase)
+
+Just to note, he also has a case design for the Bit:
+
+[https://github.com/odudex/MaixBitCase](https://github.com/odudex/MaixBitCase)
+
+### Updated website + i18n future
+The Github Pages site has been updated with new documentation and screenshots for the Amigo.
+
+A new internationalization (i18n) framework has been added by @qlrd that will allow the website to be easily translated to other languages so we can eventually have documentation for every language that Krux supports!
+
+@qlrd is also working on a graphical installer we hope to start making use of in the future when it’s ready. Keep tabs on it here: [https://github.com/qlrd/krux-installer](https://github.com/qlrd/krux-installer)
+
+
+# Version 22.03.0 - March 31, 2022
+Finally, after much TODO, the first official release of Krux is out!
+
+Krux will be following a calendar version release schedule similar to Ubuntu, hence the first release is version (20)22.03.0. If any glaring security issues or important bugfixes come up, they will make their way into point releases such as 22.03.1, 22.03.2, etc. All new work will go toward major releases which will get a new year and month combo.
+
+Thank you to everyone who contributed their time and effort toward this release. It's been very cool to see people take an interest in the project! Also, a special thank you is due to @stepansnigirev for creating the embit library that Krux leans so heavily on.
+
+## Installing
+For instructions on how to install this release, please follow the Getting Started guide on [https://selfcustody.github.io/krux/](https://selfcustody.github.io/krux/).
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..6785b16
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,164 @@
+# The MIT License (MIT)
+
+# Copyright (c) 2021-2023 Krux contributors
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# syntax=docker/dockerfile:1
+
+############
+# build-base
+# install kendryte (k210), cmake and python dependencies
+############
+FROM gcc:9.5.0-bullseye AS build-base
+
+RUN apt-get update -y && \
+ apt-get install --no-install-recommends -y -q \
+ wget \
+ tar \
+ zip \
+ unzip \
+ build-essential \
+ libtool \
+ autoconf \
+ automake \
+ autotools-dev \
+ curl \
+ libmpc-dev \
+ libmpfr-dev \
+ libgmp-dev \
+ gawk \
+ bison \
+ flex \
+ texinfo \
+ gperf \
+ libtool \
+ patchutils \
+ bc \
+ zlib1g-dev \
+ libexpat-dev \
+ libisl-dev \
+ python3 \
+ python3-pip \
+ python3-setuptools
+
+RUN mkdir -p /opt && \
+ git clone --depth 1 --recurse-submodules --shallow-submodules --branch v8.2.0-20190409 https://github.com/kendryte/kendryte-gnu-toolchain
+
+RUN cd kendryte-gnu-toolchain && \
+ export PATH=$PATH:/opt/kendryte-toolchain/bin && \
+ ./configure --prefix=/opt/kendryte-toolchain --with-cmodel=medany --with-arch=rv64imafc --with-abi=lp64f --enable-threads=posix --enable-libatomic && \
+ make -j8
+
+RUN wget https://github.com/Kitware/CMake/releases/download/v3.21.0/cmake-3.21.0.tar.gz && \
+ echo "4a42d56449a51f4d3809ab4d3b61fd4a96a469e56266e896ce1009b5768bd2ab cmake-3.21.0.tar.gz" | sha256sum -c && \
+ tar -xzvf cmake-3.21.0.tar.gz && \
+ cd cmake-3.21.0 && ./bootstrap && make && make install
+
+RUN apt-get update && apt-get install python3-venv -y
+RUN python3 -m venv /kruxenv
+RUN /kruxenv/bin/pip install astor
+RUN /kruxenv/bin/pip install pyserial==3.4
+
+
+############
+# build-software
+# copy vendor, firmware and Krux (src) files
+# install embit dependency
+############
+FROM build-base AS build-software
+ARG DEVICE="maixpy_m5stickv"
+ENV DEVICE_BUILTIN="firmware/MaixPy/projects/${DEVICE}/builtin_py"
+RUN mkdir /src
+WORKDIR /src
+
+# copy vendor to WORKDIR (src)
+COPY ./vendor vendor
+
+# clean vendor/urtypes
+RUN find vendor/urtypes -type d -name '__pycache__' -exec rm -rv {} + -depth
+
+# clean vendor/foundation-ur-py
+RUN find vendor/foundation-ur-py -type d -name '__pycache__' -exec rm -rv {} + -depth
+
+# install vendor/embit
+RUN /kruxenv/bin/pip install vendor/embit
+# clean vendor/embit
+RUN rm -rf vendor/embit/src/embit/util/prebuilt && \
+ rm -rf vendor/embit/src/embit/liquid && \
+ rm -f vendor/embit/src/embit/psbtview.py && \
+ rm -f vendor/embit/src/embit/slip39.py && \
+ rm -f vendor/embit/src/embit/wordlists/slip39.py && \
+ rm -f vendor/embit/src/embit/util/ctypes_secp256k1.py && \
+ rm -f vendor/embit/src/embit/util/py_secp256k1.py && \
+ rm -f vendor/embit/src/embit/util/py_ripemd160.py && \
+ find vendor/embit -type d -name '__pycache__' -exec rm -rv {} + -depth
+
+# copy firmware to WORKDIR (src)
+COPY ./firmware firmware
+# clean firmware
+RUN find firmware -type d -name '__pycache__' -exec rm -rv {} + -depth
+
+# copy all vendors to DEVICE_BUILTIN
+RUN cp -r vendor/urtypes/src/urtypes "${DEVICE_BUILTIN}"
+RUN cp -r vendor/foundation-ur-py/src/ur "${DEVICE_BUILTIN}"
+RUN cp -r vendor/embit/src/embit "${DEVICE_BUILTIN}"
+
+# copy Krux (src) to WORKDIR (src)
+COPY ./src src
+# rename boot.py
+RUN mv src/boot.py src/_boot.py
+# clean it
+RUN find src -type d -name '__pycache__' -exec rm -rv {} + -depth
+# copy it to DEVICE_BUILTIN
+RUN cp -r src/. "${DEVICE_BUILTIN}"
+
+
+############
+# build-firmware
+# python compilation of Krux and its dependencies inside MaixPy
+# creation of the firmware.bin
+############
+FROM build-software AS build-firmware
+ARG DEVICE="maixpy_m5stickv"
+WORKDIR /src/firmware/MaixPy
+
+# overrides the DEVICE specific C files (font, sensor, ...) in componets/micropython
+RUN cp -rf projects/"${DEVICE}"/compile/overrides/. ./
+
+RUN cd projects/"${DEVICE}" && \
+ /kruxenv/bin/python project.py clean && \
+ /kruxenv/bin/python project.py distclean && \
+ /kruxenv/bin/python project.py build && \
+ mv build/maixpy.bin build/firmware.bin
+
+
+############
+# build
+# creation of kboot.kfpkg using firmware.bin
+############
+FROM build-firmware AS build
+ARG DEVICE="maixpy_m5stickv"
+WORKDIR /src/firmware/Kboot/build
+RUN cp /src/firmware/MaixPy/projects/"${DEVICE}"/build/firmware.bin .
+
+# replace possible windows line endings
+RUN sed -i -e 's/\r$//' *.sh
+
+RUN ./CLEAN.sh && ./BUILD.sh
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..acdd5f3
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,39 @@
+
+License
+======
+
+All the source code in this repository is either MIT or Apache v2.0 licensed. Most of the source files contain a license and copyright notice, so please check the individual files and subdirectories for more information.
+
+The source code for the `MaixPy` firmware (which has been modified by the repository owner) is under the Apache v2.0 license. The source code within it related to `MicroPython` and `OpenMV` is released separately under the MIT license.
+
+The source code for the `embit` library is under the MIT license.
+The source code for the `urtypes` library is under the MIT license.
+The source code for the `foundation-ur-py` library is under the BSD-2-Clause Plus Patent license.
+The source code for the `Adafruit Thermal Printer` library is under the MIT license.
+The source code for the `Kboot` bootloader is under the Apache v2.0 license.
+
+The source code for this project created and modified by the repository owner is released under the MIT license that follows:
+
+```
+The MIT License (MIT)
+
+Copyright (c) 2021-2023 Krux contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+```
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5d63c75
--- /dev/null
+++ b/README.md
@@ -0,0 +1,314 @@
+[](https://github.com/selfcustody/krux/commit/bb8e2d63e031417111ff7cb2b8877c10e19410be)
+[](https://github.com/selfcustody/krux/releases)
+[](https://github.com/selfcustody/krux/releases)
+[](https://github.com/selfcustody/krux/graphs/contributors)
+[](https://github.com/selfcustody/krux/commits)
+[](https://codecov.io/gh/selfcustody/krux)
+[](https://calver.org)
+[](https://github.com/selfcustody/krux/blob/main/LICENSE.md)
+
+<p align="center">
+<img src="docs/img/maixpy_yahboom/logo-312.en.png" alt="yahboom" style="width: 11%;">
+<img src="docs/img/maixpy_amigo/logo-300.en.png" alt="maixpy amigo" style="width: 16%;">
+<img src="docs/img/maixpy_dock/logo-302.en.png" alt="maixpy dock" style="width: 15%;">
+<img src="docs/img/maixpy_wonder_mv/logo-304.en.png" alt="wonder mv" style="width: 11%;">
+<img src="docs/img/maixpy_m5stickv/logo-250.en.png" alt="m5stickv" style="width: 6%;">
+<img src="docs/img/maixpy_cube/logo-400.en.png" alt="maixpy cube" style="width: 10%;">
+</p>
+
+Krux is an open-source firmware facilitating the creation of Bitcoin signing devices from readily available components, such as Kendryte K210 devices. It transforms these devices into airgapped tools capable of handling transactions for both single and multisignature wallets, supporting offline signing via QR code or SD card, thus empowering users to securely self-custody their Bitcoin.
+
+---
+## Disclaimer
+**WARNING**: *This software has not yet been formally audited by a third party. Use at your own risk!*
+
+---
+
+# Getting Started
+Detailed instructions for installing and running Krux can now be found in our [official documentation](https://selfcustody.github.io/krux/).
+
+## Krux-installer
+If you just want to flash (or "install") Krux firmware on your device and are not familiar with the command line, just use our Krux-Installer.
+
+### Download our Krux-Installer
+[<img src="docs/img/badge_github.png" alt="github releases page" width="186">](https://github.com/selfcustody/krux-installer/releases)
+
+# Development
+The **instructions below are intended for programmers or developers** who would like to contribute to the project.
+
+## Download our firmware releases
+[<img src="docs/img/badge_github.png" alt="github releases page" width="186">](https://github.com/selfcustody/krux/releases)
+
+## Fetch the code
+This will download the source code of Krux as well as the code of all its dependencies inside a new folder called `krux`:
+```bash
+git clone --recurse-submodules https://github.com/selfcustody/krux
+```
+
+Note: When you wish to pull updates (to all submodules, their submodules, ...) to this repo, use:
+```bash
+git pull origin main && git submodule update --init --recursive
+```
+
+## Krux (script) (Linux or WSL)
+The [krux](krux) bash script contains commands for common development tasks. It assumes a Linux host, you will need to have [Docker Desktop or Docker Engine](https://docs.docker.com/desktop/) (don't forget to add your user to the docker group `sudo usermod -aG docker $USER`), `openssl`, and `wget` installed at a minimum for the commands to work as expected. It works on Windows using WSL. The channel Crypto Guide from Youtube made a step-by-step video - [Krux DIY Bitcoin Signer: Build From Source & Verify (With Windows + WSL2 + Docker)](https://www.youtube.com/watch?v=Vmr_TFy2TfQ)
+
+To build and flash the firmware:
+```bash
+# build firmware for Maix Amigo
+./krux build maixpy_amigo
+
+# flash the firmware to Maix Amigo
+./krux flash maixpy_amigo
+```
+
+The first time, the build can take around an hour or so to complete. Subsequent builds should take only a few minutes. If all goes well, you should see a new `build` folder containing `firmware.bin` and `kboot.kfpkg` files when the build completes.
+
+## Install Krux and dev tools
+Krux uses [Poetry](https://python-poetry.org/) as Python packaging and dependency management. This cmd installs development dependencies like [embit](https://github.com/diybitcoinhardware/embit), [ur](https://github.com/selfcustody/foundation-ur-py) and [urtypes](https://github.com/selfcustody/urtypes), and tools to run [tests](https://docs.pytest.org), review code with [pylint](https://pypi.org/project/pylint/), format code with [black](https://github.com/psf/black) and a lib to help handle i18n translations.
+```bash
+pip install poetry
+poetry install
+```
+
+If you have a problem installing Poetry on Linux OS:
+```bash
+# we considered the name of the venv .krux
+python -m venv .krux
+source .krux/bin/activate
+```
+The result will be something like:
+```bash
+(.krux) username:~/directory name$
+```
+Now you can run normaly the pip of the poetry:
+```bash
+pip install poetry
+poetry install
+```
+
+Note: when changing the dependencies in `pyptoject.toml` you need to generate a new `poetry.lock` file using the cmd: `poetry lock --no-update`.
+
+## Format code
+```bash
+poetry run poe format
+```
+
+## Review code
+```bash
+poetry run poe lint
+```
+
+## Run tests with coverage
+```bash
+poetry run poe test
+```
+
+Note: The coverage report will be created at the `htmlcov` folder `file:///path/to/krux/htmlcov/index.html`.
+
+For more verbose output (e.g., to see the output of print statements):
+```bash
+poetry run poe test-verbose
+```
+
+To run just a specific test from a specific file:
+```bash
+poetry run pytest --cache-clear ./tests/pages/test_login.py -k 'test_load_key_from_hexadecimal'
+```
+
+## Use the Python interpreter (REPL)
+This is useful for rapid development of non-visual code:
+```bash
+poetry run python
+```
+```
+Python 3.9.1
+Type "help", "copyright", "credits" or "license" for more information.
+>>> from krux.key import Key
+>>> Key("olympic term tissue route sense program under choose bean emerge velvet absurd", False).xpub()
+'tpubDCDuqu5HtBX2aD7wxvnHcj1DgFN1UVgzLkA1Ms4Va4P7TpJ3jDknkPLwWT2SqrKXNNAtJBCPcbJ8Tcpm6nLxgFapCZyhKgqwcEGv1BVpD7s'
+>>>
+```
+
+## Run the device simulator
+This is useful for rapid code development that utilizes UI/UX. It is also good for newcomers to try Krux before purchasing a device. However, the simulator does not behave exactly as the HW device and may not have all features implemented (e.g. scanning via camera a TinySeed currently only works on the HW device).
+
+Before executing, make sure you have installed the poetry extras:
+```bash
+# This cmd will uninstall other extras
+poetry install --extras simulator
+
+# To install all extras, use:
+poetry install --all-extras
+```
+
+Run the simulator:
+```bash
+# Run simulator with the touch device Amigo, then use mouse to navigate
+poetry run poe simulator
+
+# Run simulator with SD enabled (folder `simulator/sd`) on the small button-only device M5stickV, then use keyboard (arrow keys UP or DOWN and ENTER)
+poetry run poe simulator-m5stickv --sd
+
+# Run simulator on the device dock, then use keyboard (arrow keys UP or DOWN and ENTER)
+poetry run poe simulator-dock
+
+# Run simulator with the touch device yahboom, then use mouse to navigate
+poetry run poe simulator-yahboom
+
+# Run simulator on the device cube, then use keyboard (arrow keys UP or DOWN and ENTER)
+poetry run poe simulator-cube
+
+# Run simulator with the touch device wonderMV, then use mouse to navigate
+poetry run poe simulator-wonder-mv
+```
+
+Note: With emulated SD card it is possible to store settings, encrypted mnemonics, also drop and sign PSBTs. After some time running, the simulator may become slow. If that happens, just close and open again!
+
+```bash
+# ImportError: Unable to find zbar shared library
+sudo apt install python3-zbar
+
+# ImportError: libGL.so.1: cannot open shared object file: No such file or directory
+sudo apt install libgl1
+
+# `pygame.error: No available video device`
+# You are trying to run the simulator on an OS without a GUI (some kind of terminal only or WSL). Try one with GUI!
+
+# Depending on the OS, it may be necessary to install zbar-tools too:
+sudo apt install zbar-tools
+```
+
+### Simulator sequences execution
+
+This is useful for taking screenshots of device screens to use in documentation:
+```bash
+# Run all sequences of commands on all devices and in all locales (languages) [Linux OS]
+cd simulator
+./generate-all-screenshots.sh
+
+# Run a specific sequence for a specific device's with SD enabled (folder `simulator/sd`)
+poetry run poe simulator --sequence sequences/about.txt --sd
+
+# Sequence screenshots are scaled to fit in docs. Use --no-screenshot-scale to get full size
+poetry run poe simulator --sequence sequences/home-options.txt --no-screenshot-scale
+```
+
+## Live debug a device (Linux)
+It is not possible to drop into a live Python REPL anymore as we disabled the `MICROPY_ENABLE_COMPILER` flag in `firmware\MaixPy\components\micropython\port\include\mpconfigport.h`. If you enable it again it will be possible to drop into a live Python REPL by issuing an interrupt with Ctrl-C:
+
+If you've made a fresh build and flashed it to your device, you can connect to the device over serial connection with:
+```bash
+screen /dev/tty.usbserial-device-name 115200
+```
+
+If successful, the device should restart and you should see:
+```bash
+K210 bootloader by LoBo v.1.4.1
+
+* Find applications in MAIN parameters
+0: ' firmware', @ 0x00080000, size=XXX, app_size=XXX, App ok, ACTIVE
+* Loading app from flash at 0x00080000 (XXX B)
+* Starting at 0x80000000 ...
+
+
+[MAIXPY] Pll0:freq:XXX
+[MAIXPY] Pll1:freq:XXX
+[MAIXPY] Pll2:freq:XXX
+[MAIXPY] cpu:freq:XXX
+[MAIXPY] kpu:freq:XXX
+[MAIXPY] Flash:0xef:0x17
+[MaixPy] gc heap=0x8029f430-0x8036f430(851968)
+init i2c:2 freq:XXX
+[MAIXPY]: find ov7740
+[MAIXPY]: find ov sensor
+```
+Some devices like Amigo have two serial ports, check the second one if you don't read data from first.
+
+To leave `screen` serial monitor press `Ctrl+a`, followed by `k`, then confirm with `y`.
+
+## Live debug a device using MaixPy IDE (Mac or Windows)
+Use [MaixPy IDE](https://dl.sipeed.com/shareURL/MAIX/MaixPy/ide/v0.2.5) to debug the devices. Click on `Tools > Open Terminal > New Terminal > Connect to serial port > Select a COM port available` (if didn't work, try another COM port). We have removed some support for MaixPy IDE (due to size constraints), but the debug works.
+
+## WDT watchdog
+Krux makes use of MaixPy's [WDT watchdog module](https://wiki.sipeed.com/soft/maixpy/en/api_reference/machine/wdt.html), you can see it [here](src/krux/wdt.py). This will reset the device if not fed for some time. To stop the watchdog, when connected through the terminal, run the following (starting from v24.07.0 this is no loger possible because the Python real-time compiler and REPL were disabled):
+```python
+# Run this everytime you want to stop the watchdog
+
+from krux.wdt import wdt
+wdt.stop()
+```
+
+Now, with watchdog disabled, you can use debug the device normally. Also remember to disable the `Settings > Security > Shutdown Time` setting it to `0` to no more automatic resets, and if you added any print statements to the code, they should appear whenever your code is reached.
+
+## Create new translations - i18n
+The project has lots of translations [here](i18n/translations), if you add new english messages in code using `t()` function, you will need to:
+
+```bash
+# Clean unused translations:
+poetry run poe i18n clean
+
+# Create a new translation file in JSON:
+poetry run poe i18n new tr-TR
+
+# Use Google translate to create missing translations, copy them to respective files, review phrases and commas.
+poetry run poe i18n fill
+
+# Create missing translations for a single language. Ex: Brazilian Portuguese
+poetry run poe i18n fill pt-BR
+
+# Make sure all files have this new translated message:
+poetry run poe i18n validate
+
+# Format translation files properly:
+poetry run poe i18n prettify
+
+# Create the compiled table for krux translations.py
+poetry run poe i18n bake
+```
+
+## Fonts
+Learn about how to setup fonts [here](firmware/font/README.md)
+
+## Colors
+Use [this script](firmware/scripts/rgbconv.py) to generate device compatible colors from RGB values (usefull for color themes).
+
+## Documentation
+Before change documentation, and run the mkdocs server, make sure you have installed the poetry extras:
+
+```bash
+# This cmd will uninstall other extras
+poetry install --extras docs
+
+# To install all extras, use:
+poetry install --all-extras
+```
+
+To change lateral and upper menus on documentation, see `mkdocs.yml` file on `nav` section. To create or edit translations (TODO: need help!), read [here](i18n/README.md).
+
+Create the documentation site locally - `http://127.0.0.1:8000/krux/`:
+```bash
+poetry run poe docs
+```
+
+# Inspired by these similar projects
+- https://github.com/SeedSigner/seedsigner for Raspberry Pi (Zero)
+- https://github.com/diybitcoinhardware/f469-disco for the F469-Discovery board
+
+# Powered by
+- [embit](https://embit.rocks/), a Bitcoin library for Python 3 and Micropython
+- [MaixPy](https://github.com/sipeed/MaixPy), MicroPython for K210 RISC-V
+- [MicroPython](https://github.com/micropython/micropython), a lean and efficient Python implementation for microcontrollers and constrained systems
+- [Kboot](https://github.com/loboris/Kboot) and [ktool](https://github.com/loboris/ktool)
+
+# Contributing
+Issues and pull requests welcome! Let's make this as good as it can be.
+
+Feel free to start a [new discussion](https://github.com/selfcustody/krux/discussions) or an [issue](https://github.com/selfcustody/krux/issues) for work. When making your pull request, explain what it solves, ideally each PR should focus on solving one issue (exceptions can be made if the work is related or tightly coupled).
+
+**Note for PR's**: Checkout and branch off of the `develop` branch, please also make sure to explicitly target `develop`; `main` is the default branch for the latest version and also for downloading and installing Krux from source.
+
+# Support
+For technical support installing or using Krux, you can join our [Telegram chat](https://t.me/SC_Krux). Follow us on [X (Twitter)](https://x.com/selfcustodykrux) or send a message to the [Bitcoin Forum](https://bitcointalk.org/index.php?topic=5489022.0). Also check out the [DIYbitcoin chat](https://t.me/diybitcoin) on Telegram, a broader community of tinkerers, builders and hackers!
+
+Please do not use issues for support requests. If necessary, you can use our [Discussions](https://github.com/selfcustody/krux/discussions) to post your question here on GitHub.
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..d5c872e
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,100 @@
+# The MIT License (MIT)
+
+# Copyright (c) 2021-2023 Krux contributors
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure("2") do |config|
+ config.vm.box = "hashicorp/bionic64"
+ config.vm.provision :docker
+
+ config.vm.provider "virtualbox" do |vb|
+ vb.memory = 4096
+ vb.customize ['modifyvm', :id, '--usb', 'on']
+ # M5StickV https://devicehunt.com/view/type/usb/vendor/0403/device/6001
+ vb.customize ['usbfilter', 'add', '0', '--target', :id, '--name', 'FT232', '--vendorid', '0403', '--productid', '6001']
+ # Amigo + Bit https://devicehunt.com/view/type/usb/vendor/0403/device/6010
+ vb.customize ['usbfilter', 'add', '0', '--target', :id, '--name', 'FT2232', '--vendorid', '0403', '--productid', '6010']
+ # Dock https://devicehunt.com/view/type/usb/vendor/1a86/device/7523
+ vb.customize ['usbfilter', 'add', '0', '--target', :id, '--name', 'CH340', '--vendorid', '1a86', '--productid', '7523']
+ end
+end
+
+class VagrantPlugins::ProviderVirtualBox::Config < Vagrant.plugin("2", :config)
+ def update_customizations(customizations)
+ @customizations = customizations
+ end
+end
+
+class VagrantPlugins::ProviderVirtualBox::Action::Customize
+ alias_method :original_call, :call
+ def call(env)
+ machine = env[:machine]
+ config = machine.provider_config
+ driver = machine.provider.driver
+ uuid = driver.instance_eval { @uuid }
+ if uuid != nil
+ lines = driver.execute('showvminfo', uuid, '--machinereadable', retryable: true).split("\n")
+ filters = {}
+ lines.each do |line|
+ if matcher = /^USBFilterVendorId(\d+)="(.+?)"$/.match(line)
+ id = matcher[1].to_i
+ vendor_id = matcher[2].to_s
+ filters[id] ||= {}
+ filters[id][:vendor_id] = vendor_id
+ elsif matcher = /^USBFilterProductId(\d+)="(.+?)"$/.match(line)
+ id = matcher[1].to_i
+ product_id = matcher[2].to_s
+ filters[id] ||= {}
+ filters[id][:product_id] = product_id
+ end
+ end
+ config.update_customizations(config.customizations.reject { |_, command| filter_exists(filters, command) })
+ end
+ original_call(env)
+ end
+
+ def filter_exists(filters, command)
+ if command.size > 6 && command[0] == 'usbfilter' && command[1] == 'add'
+ vendor_id = product_id = false
+ i = 2
+ while i < command.size - 1 do
+ if command[i] == '--vendorid'
+ i += 1
+ vendor_id = command[i]
+ elsif command[i] == '--productid'
+ i += 1
+ product_id = command[i]
+ end
+ i += 1
+ end
+ if vendor_id != false && product_id != false
+ filters.each do |_, filter|
+ if filter[:vendor_id] == vendor_id && filter[:product_id] == product_id
+ return true
+ end
+ end
+ end
+ end
+ return false
+ end
+end
diff --git a/docs/css/custom.css b/docs/css/custom.css
new file mode 100644
index 0000000..a1724b8
--- /dev/null
+++ b/docs/css/custom.css
@@ -0,0 +1,77 @@
+.md-typeset img {
+ margin: 0 0 0.4em 0.8em !important;
+}
+
+.md-typeset img.twemoji {
+ margin: 0 !important;
+}
+
+.md-typeset h5 {
+ color: black;
+ text-transform: none;
+}
+
+img.amigo {
+ width: 16%;
+ min-width: 100px;
+}
+
+img.amigo.big {
+ width: 21%;
+}
+
+img.m5stickv {
+ width: 13%;
+ min-width: 84px;
+}
+
+img.m5stickv.big {
+ width: 17%;
+}
+
+/* Default state: no alignment */
+.align-right {
+ float: none;
+}
+
+/* Media query for screens larger than 768px */
+@media (min-width: 768px) {
+ .align-right {
+ float: right;
+ }
+}
+
+div.group-2 {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+div.group-2 div.video:first-child {
+ margin-right: auto;
+}
+
+div.video {
+ max-width: 480px;
+ margin-bottom: 2em;
+}
+
+div.video p {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+
+div.video img {
+ margin: 0 !important;
+}
+
+div.video p {
+ font-weight: 700;
+}
+
+div.clear {
+ clear: both;
+}
+
+.margin-left {
+ margin-left: 0.8em;
+}
\ No newline at end of file
diff --git a/docs/faq.en.md b/docs/faq.en.md
new file mode 100644
index 0000000..d794cc0
--- /dev/null
+++ b/docs/faq.en.md
@@ -0,0 +1,24 @@
+## Is Krux a hardware wallet?
+The term "hardware wallet" typically refers to devices dedicated to storing private keys and signing transactions. These devices often feature specific security components like secure element chips.
+
+Krux was initially developed as a signer, operating exclusively in amnesic mode, which requires users to load their keys each time the device is powered on. However, Krux has evolved and now offers the option to store mnemonics, similar to traditional hardware wallets. These mnemonics can be stored in the device's internal memory or on SD cards.
+
+Krux does not include hardware secure elements. The security of stored data relies on encryption. Read more about [Krux Encryption - Regarding BIP39 Mnemonics](getting-started/features/encryption/encryption.md/#regarding-bip39-mnemonics).
+
+**Note**: Due to the inherent fragility of electronic components, never use your Krux device or SD card encrypted storage as your sole backup method. Always maintain a physical backup for added security.
+
+## What is the test (beta) version?
+The test (beta) version includes the latest and most experimental features, which we occasionally share on our social media. The firmware can be found exclusively in the [test (beta) repository](https://github.com/odudex/krux_binaries). Use and flash the beta firmware if you are curious about new features or want to participate in the development process by hunting bugs, providing feedback, and sharing ideas in our Telegram groups or other social media platforms.
+
+Just remember that for regular use, use the official versions, which are signed, thoroughly tested, and well documented.
+
+## What is Krux Mobile Android app?
+
+### How can I find it?
+The Krux Mobile Android app is considered a test (beta) and is available as an APK at [KruxMobileApp](https://github.com/selfcustody/KruxMobileApp). It requires Android 6.0 or above.
+
+### How can I install it?
+The APK is not available on the Play Store. You can download the APK directly or transfer it to your Android device via SD card or USB cable. To install it, you may need to configure your Android device to allow installations from unknown sources.
+
+### Is it safe to use?
+The Krux Mobile Android app is designed for learning about Krux and Bitcoin air-gapped transactions. Due to the numerous potential vulnerabilities inherent in smartphones, such as the lack of control over the operating system, libraries, and hardware peripherals, the Krux app **should NOT be used** to manage wallets containing savings or **important keys and mnemonics**. For secure management of your keys, **a dedicated device** is recommended.
diff --git a/docs/getting-started/features/QR-transcript-tools.en.md b/docs/getting-started/features/QR-transcript-tools.en.md
new file mode 100644
index 0000000..d039a55
--- /dev/null
+++ b/docs/getting-started/features/QR-transcript-tools.en.md
@@ -0,0 +1,49 @@
+When you export a mnemonic, encrypted mnemonic or a generic text QR code, alternative visualization modes will be available. Swipe left :material-gesture-swipe-left: or right :material-gesture-swipe-right: to change modes, or if your device doesn't have a touchscreen, press the `PAGE` buttons. See our [available transcribe templates](../templates/templates.md).
+
+### Standard Mode
+<img src="../../../img/maixpy_m5stickv/standard-qr-code-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/standard-qr-code-300.png" align="right" class="amigo">
+
+This mode is optimized for scanning, the raw QR code will be displayed
+
+<div style="clear: both"></div>
+
+### Lines Mode
+<img src="../../../img/maixpy_m5stickv/lines-qr-code-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/lines-qr-code-300.png" align="right" class="amigo">
+
+If you are good at transcribing things like handwritten text, with this mode one QR code line will be highlighted at a time. Press `ENTER` to highlight the next line.
+
+<div style="clear: both"></div>
+
+### Zoomed Regions Mode
+<img src="../../../img/maixpy_m5stickv/zoomed-qr-code-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/zoomed-qr-code-300.png" align="right" class="amigo">
+
+QR codes will be split into regions, of 5x5 or 7x7 "blocks". One QR code region will be shown at a time. Press `ENTER` to display the next region.
+
+<div style="clear: both"></div>
+
+### Highlighted Regions Mode
+<img src="../../../img/maixpy_m5stickv/regions-qr-code-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/regions-qr-code-300.png" align="right" class="amigo">
+
+QR codes will be split into regions, of 5x5 or 7x7 "blocks". One QR code region will be highlighted at a time. Press `ENTER` to highlight the next region.
+
+<div style="clear: both"></div>
+
+### Grided Mode
+<img src="../../../img/maixpy_m5stickv/grided-qr-code-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/grided-qr-code-300.png" align="right" class="amigo">
+
+Grids will be added to a standard QR code. In a dark room, if you place a sheet of paper over the device's screen, you'll notice QR code will be visible and it will be possible to copy it directly from above (tracing). Be careful not to damage your screen with pen and markers, use an insulating plastic tape or film to protect the device when using this method.
+
+<div style="clear: both"></div>
+
+### QR Viewer
+<img src="../../../img/maixpy_m5stickv/qr-viewer-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/qr-viewer-300.png" align="right" class="amigo">
+
+Almost every QR code in Krux will also bring up this menu with these extra options: `Toggle Brightness`, `Save QR Image to SD Card` and `Print as QR`. If `Save QR Image to SD Card` shows as disabled it means that the SD card was not detected. To enable `Print as QR` you need to configure your printer driver in [settings](../settings.md#printer).
+
+<div style="clear: both"></div>
diff --git a/docs/getting-started/features/encryption/encryption.en.md b/docs/getting-started/features/encryption/encryption.en.md
new file mode 100644
index 0000000..6c41bcf
--- /dev/null
+++ b/docs/getting-started/features/encryption/encryption.en.md
@@ -0,0 +1,98 @@
+Encryption is an advanced feature for securely hiding a secret. However, if used incorrectly, the secret may become unrecoverable without a separate plain-text backup. Before using it, carefully review this document and pay close attention to all warnings.
+
+### In General
+In **Settings -> Encryption Settings**, you can adjust *PBKDF2 Iterations* and *Encryption Mode* before loading a wallet. When encrypting, Krux applies these preferences to optimize for the specific secret being secured, producing an encrypted KEF envelope that can be exported as a QR or saved to SD.
+
+During encryption, users may be prompted to override their preferences or select a specific version. Most importantly: **the encryption key MUST be strong**. If a KEF envelope is created with a weak key and shared or exposed, it should be assumed to offer **NO protection**, and the secret will be leaked.
+
+<img src="../../../../img/maixpy_m5stickv/load-mnemonic-kef-via-qr-250.png" align="right" class="m5stickv">
+<img src="../../../../img/maixpy_amigo/load-mnemonic-kef-via-qr-300.png" align="right" class="amigo">
+
+When Krux detects data resembling a KEF-encrypted envelope, it prompts the user to *"Decrypt?"*, showing the KEF version, envelope ID (or label), and the PBKDF2 iteration count used during creation. To decrypt, the same key (typed or scanned) must be provided. Once unlocked, Krux uses the plaintext within context. If decryption is declined, the raw envelope is used instead—usually resulting in an error, since KEF data is meaningless without decryption.
+
+<div style="clear: both"></div>
+
+KEF envelopes are deliberately opaque, providing no information about their contents or the key needed for decryption. It is the user’s responsibility to track this—by noting what each envelope contains, how to decrypt it, and assigning an ID at encryption to help recall its contents and locate the correct key. During encryption, Krux suggests an ID that the user can modify. For mnemonics, the default ID is the wallet fingerprint without a passphrase; for wallet output descriptors, it defaults to the wallet’s generic policy.
+
+Within the Tools menu, users may experiment with [Datum tool](../tools.md/#datum-tool) for encrypting small to mid-sized contents (less than 50K bytes) and for decrypting KEF envelopes.
+
+### Regarding BIP39 Mnemonics
+
+There are several ways to add security layers to a wallet’s private key. The most common is adding a BIP39 passphrase to the mnemonic. Encrypting a BIP39 mnemonic serves a similar purpose, but differs in a key way: with BIP39 passphrases, entering the wrong passphrase loads a different wallet, while with Krux’s encrypted mnemonics, a wrong key simply returns an error. Depending on the use case, this behavior may be preferable. Krux’s implementation also stores a mnemonic ID alongside the data for convenience. Encrypted mnemonics can be combined with a BIP39 passphrase for added security, and the same mnemonic can be encrypted with multiple different keys.
+
+## AES Modes-of-Operation
+
+Krux uses standard AES encryption with modes-of-operation: ECB, CBC, CTR and GCM. The user may set their preference within `Settings, Encryption Settings, Encryption Mode`. Krux uses GCM as the default mode-of-operation, but you may have valid reasons for making your own choice, ie:
+
+* maybe you want compatibility with other software or devices you use,
+* maybe you want the smallest QR possible for high-entropy secrets like mnemonics or passhprases,
+* etc.
+
+### AES-ECB
+
+ECB (Electronic Codebook) is a simpler method where data blocks are encrypted individually. This mode is faster and simpler to encrypt, resulting in QR codes with lower density that are easier to [transcribe](../QR-transcript-tools.md). It is generally considered less secure than others because it does not provide data chaining, meaning identical plaintext blocks would produce identical ciphertext blocks, making it vulnerable to pattern analysis. However, in Krux's implementation, encrypting plaintext via ECB which contains duplicate blocks has been intentionally disabled.
+
+### AES-CBC
+
+CBC (Cipher-block Chaining) is considered more secure than ECB. In the first data block, an initialization vector (IV) is used to add random data to the encryption. The encryption of subsequent blocks depends on the data from previous blocks, characterizing chaining. Tradeoffs are that encryption/decryption must be done in series and when encrypting, a camera snapshot will be needed to generate the IV, so it's a slower process. The IV will always stored together with encrypted data, making encrypted QR codes denser and harder to [transcribe](../QR-transcript-tools.md). This mode is often available on other microcontroller devices.
+
+### AES-CTR
+CTR (Counter Mode) like CBC is more secure than ECB, because of the use of an Initialization Vector, and also most efficient as a stream cipher, capable of encrypting and decrypting in parallel. This mode is often available on other microcontroller devices.
+
+### AES-GCM
+GCM (Galois Counter-Mode). Similar to CBC and CTR, the cipher is initialized with a nonce from a camera snapshot. Like CTR, it is a paralellizable stream cipher, and also adds Galois Field authentication inherently. Capable of optimized performance, with built-in authentication and ease of implementation, this mode is the Krux default unless the user has selected otherwise.
+
+### Initialization Vector
+
+Modes ECB, CBC, and GCM use an Initialization Vector (IV), where IV is better termed `nonce` for GCM. The IV will be generated from a snapshot taken with the camera. It is a fixed-size input value used to initialize the cipher, adding randomness to the encryption, and ensuring that data encrypted with the same key will produce different ciphertexts each time. The IV, or nonce, is not secret and will be transmitted along with the ciphertext. However, like any nonce, it should not be reused to maintain security.
+
+## Key Stretching (PBKDF2 Iterations)
+
+When you enter the encryption key, it is not directly used to encrypt your data. In order to protect against brute force attacks, the user supplied key is derived multiple times -- stretched to 256 bits via `pbkdf2_hmac_sha256`. PBKDF2 (Password-Based Key Derivation Function) Iterations refer to the number of derivations that will be performed over your key -- as the `password` -- `salted` with an ID, prior to encrypting/decrypting your secret. Users may set a preferred `PBKDF2 Iterations` value in `Encryption Settings`, then Krux will propose a slightly different value -- within a 10% delta, whenever encrypting.
+
+
+## KEF Encryption Format
+When Krux encrypts a secret, the result is a `KEF Envelope` -- which is a series of bytes. Each envelope is constructed similarly, containing fixed-length and variable-length fields representing: a custom `ID` for the envelope, a `Version`, number of PBKDF2 `Iterations`, and a `Cipher PayLoad`, so that any devices or software supporting KEF may recognize the envelope and know how to decrypt it -- given the correct `key`. These fields, within each KEF envelope are:
+
+| ID length (1) | ID (2) | Version (3) | Key Derivations (4) | Cipher PayLoad (5, 6, and 7) |
+| :---: | :---: | :---: | :---: | :---: |
+| 1 Byte | Variable | 1 Byte | 3 Bytes | Variable |
+
+* **Visible data** (1 to 4):
+ * **(1)** Mnemonic ID length (1 Byte).
+ * **(2)** Mnemonic ID (variable length): Custom `ID` (wallet fingerprint for mnemonics).
+ * **(3)** Version (1 Byte): Version of encryption method; currently twelve are available -- details later.
+ * **(4)** key derivation Iterations (3 bytes): Number of PBKDF2 key derivations. if <= 10,000, multiplied by 10,000.
+* **Cipher PayLoad** (5, 6, and 7):
+ * **(5)** IV (12 or 16 bytes, optional): Initialization Vector for modes: CBC or CTR, and nonce for GCM.
+ * **(6)** Encrypted Ciphertext.
+ * **(7)** Authentication/validation data (3, 4, or 16 bytes).
+
+### Version Details
+While all KEF envelopes share the above format, each version differs -- offering choices to the user, as trade-offs that may better fit a particular use-case. For technical details, see: [KEF specifications](kef-specifications.md)
+
+| Version | Name | Mode | IV | Compressed | Intended Use Case |
+|---------|------------|------|----|------------|----------------------------------------|
+| 0 | AES-ECB v1 | ECB | -- | -- | Legacy (<= v25.03.0): mnemonic entropy |
+| 1 | AES-CBC v1 | CBC | 16 | -- | Legacy (<= v25.03.0): mnemonic entropy |
+| | | | | | |
+| 5 | AES-ECB | ECB | -- | -- | Smallest QR; mnemonic, passphrase |
+| 6 | AES-ECB +p | ECB | -- | -- | General Mid-sized |
+| 7 | AES-ECB +c | ECB | -- | Yes | Large; repetitive text |
+| | | | | | |
+| 10 | AES-CBC | CBC | 16 | -- | Small, high-entropy |
+| 11 | AES-CBC +p | CBC | 16 | -- | General mid-sized |
+| 12 | AES-CBC +c | CBC | 16 | Yes | General large |
+| | | | | | |
+| 15 | AES-CTR | CTR | 12 | -- | General mid-sized |
+| 16 | AES-CTR +c | CTR | 12 | Yes | General large |
+| | | | | | |
+| 20 | AES-GCM | GCM | 12 | -- | Default; General mid-sized |
+| 21 | AES-GCM +c | GCM | 12 | Yes | Default; General large |
+
+
+## Considerations
+Storage of encrypted secrets on the device or SD cards are meant for convenience only and should not be considered a long-term form of backup. Always make a physical backup of your keys that is independent from electronic devices and test recovering your wallet from this backup before you send funds to it. Flash storage can degrade over time and may be subject to permanent damage, resulting in the loss of stored information.
+
+Remember that any encrypted secret is protected by the key you defined to encrypt it. If the defined [key is weak](https://www.hivesystems.com/blog/are-your-passwords-in-the-green), your encrypted mnemonic and other secrets will **not be protected**. If you have stored sensitive secrets in the device's internal flash memory using a [weak key](https://www.hivesystems.com/blog/are-your-passwords-in-the-green), the best way to undo this is to [erase user's data](../tools.md/#erase-users-data).
+
diff --git a/docs/getting-started/features/encryption/kef-specifications.en.md b/docs/getting-started/features/encryption/kef-specifications.en.md
new file mode 100644
index 0000000..d12443b
--- /dev/null
+++ b/docs/getting-started/features/encryption/kef-specifications.en.md
@@ -0,0 +1,464 @@
+# KEF Encryption Format -- Technical Specification
+
+...`The K stands for "KEF"` --anon
+
+
+## Motivation
+
+In the autumn of 2023, during the lead-up to **krux release 23.09.0**, contributors proposed a method of encrypting bip39 mnemonics that could be stored in SPI-flash, on sdcard, and/or exported to QR. Regarding the encrypted-mnemonic QR format: the layout proposed was interesting as an extensible, lite-weight, self-describing envelope that has been appreciated by users ever since.
+
+...`"Wen passphrases, output descriptors, PSBTs, and notes?"` --plebs
+
+This specification, and its accompanying implementation and test-suite are the result of months of exploration into improvements meant to better define, test, and extend the original encryption format that we'll refer to as KEF. It proposes ten new versions, extending its usefulness to more than mnemonics, targeting variable-length strings up to moderately sized PSBTs, flexibility to choose among four AES modes of operation, with-or-without compression, and versions optimized to result in a smaller envelope.
+
+Above all, this specification aims to be supported by as many projects as would consider adopting it, so that users are not "locked" into a particular project when recovering their secrets. Corrections and refinement to, and scrutiny of this specification are appreciated. Proposals for more `versions` are welcome, provided they offer "value" to the user and fit within the scope of this system. Once released, because it cannot be known how many KEF envelopes may exist in-the-wild, changes to any particular version must remain backwards compatible for decryption. Adopting implementations are free to support any KEF versions they wish to support, for decryption-only or for both encryption and decryption -- with the expectation that claims-of-support made are clear and precise about what is supported.
+
+## Overview
+
+This system encrypts arbitrary plaintext into a versioned, self-describing, **KEF envelope** which includes:
+
+* custom identity/label `len_id` and `id`
+* version `v`
+* pbkdf2-hmac iterations `i`
+* and cipher-payload `cpl`
+
+where cipher-payload `cpl` consists of:
+
+* Initialization-Vector/Nonce (if applicable) `IV`
+* ciphertext
+* and authentication/validation data `auth`
+
+KEF versions offer combinations of different **modes-of-operation**, **authentication strategies**, **padding strategies**, and **compression**, all selected via a numeric version code (0 - 21).
+
+* Available version codes are: 0, 1, 5, 6, 7, 10, 11, 12, 15, 16, 20, 21. Not all integers in the range are assigned, and implementations may disable versions or modes.
+
+Currently, all versions use AES and derive the 256-bit encryption key `k` as:
+```
+k = pbkdf2_hmac_sha256(K, id, i)
+```
+
+where:
+
+* `K` = user-provided password/key material (bytes; if str: non-normalized encode as utf-8)
+* `id` = salt (variable-length, prepended to envelope; bytes: if str: non-normalized encode as utf-8)
+* `i` = iteration count (3 bytes, big-endian)
+
+The stored iteration field `i` MUST be ≥ 1. The effective PBKDF2 iteration count is `i` if `i > 10,000`, otherwise `i * 10,000`.
+
+Compression (when enabled) uses zlib.compress(wbits=-10) or raw deflate(micropython).
+
+Authentication has three forms:
+
+* When the mode has built-in authentication, like GCM: `auth` is a truncated auth tag
+* When the mode does not have built-in authentication, `auth` is a truncated sha256 digest whose pre-image is of two forms:
+ * if `auth` will be encrypted with plaintext, hidden, it is `sha256(plaintext)`
+ * if `auth` will be appended to ciphertext, exposed, it is `sha256(version || IV || plaintext || derived-k)`
+
+## Generalizations Regarding Implementation
+
+It is expected that any implementation can decrypt a KEF envelope that was created by itself on the same device. Implementations are asked to make their "best-effort" to be capable of decrypting KEF envelopes for versions they support which were created by other implementations or on other devices -- but this will not always be possible. Decrypting large KEF envelopes on severely constrained devices, or ones created with flawed implementations is unrealistic. Therefore, in such cases it is the responsibility of the user to find an implementation and device capable of decrypting their KEF envelope, or to have a non-KEF form of recovery.
+
+* Be strict while encrypting. Be tolerant -- and non-specific about errors, when decrypting.
+
+* At its base, **a KEF envelope is a format of bytes -- so are all of its inputs**. Remember this when converting strings gathered for the `key` and `id`. Consider being strict about offering a reasonably minimal set of characters, common and available on other devices and/or international keyboards when encrypting -- then encode unicode codepoints (if not ascii) directly to their utf-8 representations without normalization. For decryption, more characters could be offered when gathering the `key`, and multiple normalization strategies may be tried, so that secrets may be recovered. Consider some capability of displaying both `key` and `id` as bytes, and gathering the `key` as bytes either directly or via hex/base64 conversion if necessary, to enable recovery. Do NOT assume that a user originally used a particular implementation to encrypt a KEF envelope.
+
+* **On the importance of a STRONG user-supplied `key`** This cannot be stressed enough to each user of KEF. While KEF allows for key-stretching via `id` and `iterations`, and offers modes that require a random `IV` / Nonce, **KEF offers no expectation of security for a weak user-supplied `key`**. Consider making this point clear to users before encrypting and/or offer an indication of `key` strength once gathered. If a KEF envelope has been created with a "weak" `key` and stored accessible to others, user should assume that their secret has been leaked. Consider encouraging users to make sane choices about the characters they use in their `key`, aware that non-ascii characters offered by one implementation may not be easy to enter on another, or that a recognizable glyph may not exist on other devices for them to verify their `key` when decrypting.
+
+* **On security** Not all KEF `versions` offer the same security guarantees, so implementors MUST take care to protect against "unsafe" usage. As already mentioned: be strict and fail to encrypt when "unsafe"; be tolerant and vague while decrypting. Support for decrypt-only on a particular version is perfectly valid should an implementation choose to "nudge" users towards a more-secure version where it supports full encrypt/decrypt functionality.
+
+ * **On mode ECB**: Repeated blocks would leak patterns within ciphertext. Therefore, be strict -- refuse to encrypt using mode ECB whenever duplicate blocks are detected. Consider a compressed version which may resolve this.
+
+ * **On block modes with NUL padding** Problems to unpad can arise decrypting where valid NUL bytes are confused with removable padding.
+ * If `auth` is appended to plaintext before padding AND the `auth` bytes end in 0x00: be strict -- refuse to encrypt. Consider a version with safe padding.
+ * If `auth` is appended to ciphertext after padding/encryption AND the `plaintext` bytes end in 0x00: be strict -- refuse to encrypt. Consider a version with safe padding.
+ * Do not assume that other implementations adhere to the above. Be tolerant and make reasonable efforts to successfully recover secrets when decrypting. Offering a warning to users AFTER successful decryption in this case may be appropriate.
+
+* **On modes that require IV or Nonce** Take precautions to ensure that this value is random and not reused. ie: Natural entropy captured from camera sensor (user validated and/or analyzed to ensure sensor is working / high entropy).
+
+* **On common `bytes` encodings** Outside the strict scope that **KEF envelopes are a format of bytes** but related to this topic: implementations may be presented with encoded strings that are likely to represent bytes. For instance: base64, base43 (from electrum), base32, or hex might be representations of a KEF envelope that was previously encoded for transport. As you continue reading, it will become clear that with any bytestring, one may recognize a KEF envelope by:
+ 1. reading the first byte as an integer `len_id`,
+ 2. jumping that many bytes, over the `id`, to read the next byte as an integer `version`,
+ 3. if that version represents a known and supported KEF version, then the rest of the envelope may be parsed via that version's KEF rules.
+ 4. if parsing succeeds without errors, it is likely to be a KEF envelope and a decryption user-interface should be offered to the user.
+ While the user likely knows, the process instance of a KEF implementation will learn definitively, only AFTER a successful decryption, that a bytestring was indeed a KEF envelope. If at any point along this process, an implementation finds that `version` is unknown/disabled, or if parsing fails, the expected action is NOT TO RAISE SPECIFIC ERRORS regarding this inspection. Rather, the appropriate action is to assume it was not a KEF envelope and to treat the data under another context: ie: "Unknown". Similarly, as mentioned above, being vague about errors during decryption implies that "Failed!" may be a sufficient response for any error, instead of leaking to a potential attacker specific details about the failure.
+
+* **On Iterations** Consider that users may want to decrypt KEF envelopes on various resource-constrained devices. There is a minimum 10,000 iterations imposed in any KEF envelope (a value of 1 would be 10,000 pbkdf2_hmac iterations), and the maximum could be as high as 100,000,000 (a value of 10,000), but depending on the device used, 500,000 might be too high. Also, since the user-supplied `key` is stretched by this value, consider offering a range to users -- then adding a small `delta` as extra bits of entropy to derive different AES-256 keys that would otherwise be the same in the event the user re-uses the same `key`, `id` and `iterations` when creating many KEF envelopes.
+
+* **On truncated Authentication** At first glance it may be concerning that `auth` bytes for many versions have been truncated and are trivially "weak". Note that KEF's use-case for authentication is to validate that the user has correctly entered their decryption `key`. In the worse case, "false-authenticated" success will occur at a rate of 1:16M (or 1:4B for others) if using an incorrect decryption `key`; similar if an attacker has modified the KEF envelope. In these "false-authenticated" success cases, data will result from decryption, but that data will NOT be the original secret or plaintext; it will be of no value.
+
+## Common Structure of a KEF Envelope
+
+All KEF versions' encrypted outputs follow this layout:
+```
+len_id + id + v + i + cpl
+```
+
+| Field | Size | Description |
+|-----------|----------------|-------------|
+| `len_id` | 1 byte | Length of `id` (0 - 252) |
+| `id` | `len_id` bytes | Salt for PBKDF2 |
+| `v` | 1 byte | Version number |
+| `i` | 3 bytes | Iteration count (big-endian; if <= 10,000: *= 10,000) |
+| `cpl` | Variable | Cipher PayLoad (IV + ciphertext + auth) |
+
+The Cipher PayLoad `cpl` structure varies by version.
+
+---
+
+### Versions - Details
+
+Details for currently-available versions of KEF follow. The top half of each section is pre-formatted `self-doc` text, built from the reference implementation's test-suite (using KEF `VERSION` constants as KEF's rule-set). The bottom half of each section with rich-formatted text was initially LLM-generated, prompted with the `self-doc` text, then curated and edited by hand.
+
+
+#### v0: "AES-ECB v1"
+
+```
+[AES-ECB v1] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =0
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: e.encrypt(P + auth + pad)
+e: AES(k, ECB)
+auth: sha256(P)[:16]
+pad: NUL
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: ECB
+* **IV**: None
+* **Padding**: NUL bytes to block boundary
+* **Authentication**: First 16 bytes of `SHA256(plaintext)`, hidden
+* **cpl layout**: `[ciphertext]` (auth embedded before padding/encryption)
+* **Use Case**: LEGACY: consider using version 5; encryption of 16 or 32 BIP39 entropy bytes
+* **Security Note**: When encrypting: fail "unsafe" if duplicate plaintext blocks, fail "unsafe" if auth ends 0x00
+
+---
+
+#### v1: "AES-CBC v1"
+
+```
+[AES-CBC v1] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =1
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(P + auth + pad)
+iv: 16b
+e: AES(k, CBC, iv)
+auth: sha256(P)[:16]
+pad: NUL
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: CBC
+* **IV**: 16 bytes
+* **Padding**: NUL bytes to block boundary
+* **Authentication**: First 16 bytes of `SHA256(plaintext)`, hidden
+* **cpl layout**: `[iv (16)] + [ciphertext]` (auth embedded before padding/encryption)
+* **Use Case**: LEGACY: consider using version 10; encryption of 16 or 32 BIP39 entropy bytes
+* **Security Note**: When encrypting: do not re-use IV, fail "unsafe" if auth ends 0x00
+
+---
+
+#### v5: "AES-ECB"
+
+```
+[AES-ECB] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =5
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: e.encrypt(P + pad) + auth
+e: AES(k, ECB)
+pad: NUL
+auth: sha256(v + P + k)[:3]
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: ECB
+* **IV**: None
+* **Padding**: NUL bytes to block boundary
+* **Authentication**: First 3 bytes of `SHA256(version_byte + plaintext + derived_key)`, exposed
+* **cpl layout**: `[ciphertext] + [auth (3)]`
+* **Use Case**: smallest KEF envelope for high-entropy secrets (BIP39 entropy, passphrase, cryptographic keys)
+* **Security Note**: When encrypting: fail "unsafe" if duplicate plaintext blocks, fail "unsafe" if plaintext ends 0x00
+
+---
+
+#### v6: "AES-ECB +p"
+
+```
+[AES-ECB +p] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =6
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: e.encrypt(P + auth + pad)
+e: AES(k, ECB)
+auth: sha256(P)[:4]
+pad: PKCS7
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: ECB
+* **IV**: None
+* **Padding**: PKCS7 to block boundary
+* **Authentication**: First 4 bytes of `SHA256(plaintext)`, hidden
+* **cpl layout**: `[ciphertext]` (auth embedded before padding/encryption)
+* **Use Case**: Mid-sized variable length plaintext
+* **Security Note**: When encrypting: fail "unsafe" if duplicate plaintext blocks
+
+---
+
+#### v7: "AES-ECB +c"
+
+```
+[AES-ECB +c] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =7
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: e.encrypt(zlib(P, wbits=-10) + auth + pad)
+e: AES(k, ECB)
+auth: sha256(zlib(P, wbits=-10))[:4]
+pad: PKCS7
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: ECB
+* **IV**: None
+* **Compression**: `zlib.compress(P, wbits=-10)`, - raw deflate
+* **Padding**: PKCS7 to block boundary
+* **Authentication**: First 4 bytes of `SHA256(plaintext)`, hidden
+* **cpl layout**: `[ciphertext]` (auth embedded after compression, before padding/encryption)
+* **Use Case**: Mid-sized variable length plaintext
+* **Security Note**: like others, when encrypting: fail "unsafe" if duplicate blocks -- unlikely with compression
+
+---
+
+#### v10: "AES-CBC"
+
+```
+[AES-CBC] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =10
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(P + pad) + auth
+iv: 16b
+e: AES(k, CBC, iv)
+pad: NUL
+auth: sha256(v + iv + P + k)[:4]
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: CBC
+* **IV**: 16 bytes, random, prepended in `cpl`
+* **Padding**: NUL bytes to block boundary
+* **Authentication**: First 4 bytes of `SHA256(v + iv + P + k)`, exposed
+* **cpl layout**: `[iv (16)] + [ciphertext] + [auth (4)]`
+* **Use Case**: Mnemonics, passphrases, short secrets
+* **Security Note**: When encrypting: do not re-use IV, fail "unsafe" if plaintext ends 0x00
+
+---
+
+#### v11: "AES-CBC +p"
+
+```
+[AES-CBC +p] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =11
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(P + auth + pad)
+iv: 16b
+e: AES(k, CBC, iv)
+auth: sha256(P)[:4]
+pad: PKCS7
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: CBC
+* **IV**: 16 bytes, random, prepended in `cpl`
+* **Padding**: PKCS7 to block boundary
+* **Authentication**: First 4 bytes of `SHA256(plaintext)`, hidden
+* **cpl layout**: `[iv] + [ciphertext]` (auth embedded before padding/encryption)
+* **Use Case**: General mid-sized plaintext
+* **Security Note**: When encrypting: do not re-use IV
+
+---
+
+#### v12: "AES-CBC +c"
+
+```
+[AES-CBC +c] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =12
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(zlib(P, wbits=-10) + auth + pad)
+iv: 16b
+e: AES(k, CBC, iv)
+auth: sha256(zlib(P, wbits=-10))[:4]
+pad: PKCS7
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: CBC
+* **IV**: 16 bytes, random, prepended in `cpl`
+* **Compression**: `zlib.compress(P, wbits=-10)`, - raw deflate
+* **Padding**: PKCS7 to block boundary
+* **Authentication**: First 4 bytes of `SHA256(compressed plaintext)`, hidden
+* **cpl layout**: `[iv (16)] + [ciphertext]` (auth embedded after compression, before padding/encryption)
+* **Use Case**: Larger plaintext
+* **Security Note**: When encrypting: do not re-use IV
+
+---
+
+#### v15: "AES-CTR"
+
+```
+[AES-CTR] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =15
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(P + auth)
+iv: 12b
+e: AES(k, CTR, iv)
+auth: sha256(P)[:4]
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: CTR
+* **IV**: 12 bytes, random, prepended in `cpl`
+* **Padding**: None
+* **Authentication**: First 4 bytes of `SHA256(plaintext)`, hidden
+* **cpl layout**: `[iv (12)] + [ciphertext]` (auth embedded before padding/encryption)
+* **Use Case**: Small to mid-sized plaintext
+* **Security Note**: When encrypting: do not re-use IV
+
+---
+
+#### v16: "AES-CTR +c"
+
+```
+[AES-CTR +c] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =16
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(zlib(P, wbits=-10) + auth)
+iv: 12b
+e: AES(k, CTR, iv)
+auth: sha256(zlib(P, wbits=-10))[:4]
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: CTR
+* **IV**: 12 bytes, random, prepended in `cpl`
+* **Compression**: `zlib.compress(P, wbits=-10)`, - raw deflate
+* **Padding**: None
+* **Authentication**: First 4 bytes of `SHA256(compressed plaintext)`, hidden
+* **cpl layout**: `[iv (12)] + [ciphertext]` (auth embedded after compression, before padding/encryption)
+* **Use Case**: Larger plaintext
+* **Security Note**: When encrypting: do not re-use IV
+
+---
+
+#### v20: "AES-GCM"
+
+```
+[AES-GCM] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =20
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(P) + auth
+iv: 12b
+e: AES(k, GCM, iv)
+auth: e.authtag[:4]
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: GCM
+* **IV/Nonce**: 12 bytes, random, prepended in `cpl`
+* **Padding**: None
+* **Authentication**: First 4 bytes of GCM authtag, exposed
+* **cpl layout**: `[iv (12)] + [ciphertext] + [auth (4)]`
+* **Use Case**: DEFAULT: Small to mid-sized plaintext
+* **Security Note**: When encrypting: do not re-use IV/Nonce
+
+---
+
+#### v21: "AES-GCM +c"
+
+```
+[AES-GCM +c] KEF bytes: len_id + id + v + i + cpl
+len_id: 1b
+id: <len_id>b
+v: 1b; =21
+i: 3b big; =(i > 10K) ? i : i * 10K
+cpl: iv + e.encrypt(zlib(P, wbits=-10)) + auth
+iv: 12b
+e: AES(k, GCM, iv)
+auth: e.authtag[:4]
+k: pbkdf2_hmac_sha256(K, id, i)
+```
+
+* **Mode**: GCM
+* **IV/Nonce**: 12 bytes, random, prepended in `cpl`
+* **Compression**: `zlib.compress(P, wbits=-10)`, - raw deflate
+* **Padding**: None
+* **Authentication**: First 4 bytes of GCM authtag, exposed
+* **cpl layout**: `[iv (12)] + [ciphertext] + [auth (4)]`
+* **Use Case**: DEFAULT: Larger plaintext
+* **Security Note**: When encrypting: do not re-use IV/Nonce
+
+---
+
+#### Summary Table
+
+| Ver | Name | Mode | IV | Padding | Compress | Authentication Method | Auth | Intended Use Case |
+|-----|------------|------|----|---------|----------|------------------------|-------------|-------------------------|
+| 0 | AES-ECB v1 | ECB | – | NUL | No | SHA256(plaintext)[:16] | 16 B | Legacy high-entropy |
+| 1 | AES-CBC v1 | CBC | 16 | NUL | No | SHA256(plaintext)[:16] | 16 B | Legacy high-entropy |
+| 5 | AES-ECB | ECB | – | NUL | No | SHA256(v+P+k)[:3] | 3 B exposed | Small, high-entropy |
+| 6 | AES-ECB +p | ECB | – | PKCS7 | No | SHA256(plaintext)[:4] | 4 B | General Mid-sized |
+| 7 | AES-ECB +c | ECB | – | PKCS7 | Yes | SHA256(compressed)[:4] | 4 B | Large; duplicate blocks |
+| 10 | AES-CBC | CBC | 16 | NUL | No | SHA256(v+iv+P+k)[:4] | 4 B exposed | Small, high-entropy |
+| 11 | AES-CBC +p | CBC | 16 | PKCS7 | No | SHA256(plaintext)[:4] | 4 B | General mid-sized |
+| 12 | AES-CBC +c | CBC | 16 | PKCS7 | Yes | SHA256(compressed)[:4] | 4 B | General large |
+| 15 | AES-CTR | CTR | 12 | – | No | SHA256(plaintext)[:4] | 4 B | General mid-sized |
+| 16 | AES-CTR +c | CTR | 12 | – | Yes | SHA256(compressed)[:4] | 4 B | General large |
+| 20 | AES-GCM | GCM | 12 | – | No | GCM authtag[:4] | 4 B exposed | Best, General mid-sized |
+| 21 | AES-GCM +c | GCM | 12 | – | Yes | GCM authtag[:4] | 4 B exposed | Best, General large |
+
+---
+
+## KEF Implementation Concepts
+
+Using examples from, and as an introduction to the reference [KEF implementation](https://github.com/selfcustody/krux/blob/develop/src/krux/kef.py), we'll quickly cover some basic concepts that may be helpful in getting started with your own KEF implementation.
+
+### Version Configuration
+From the version details and summary table: note that all KEF versions can be defined as having a set of parameters which define that version's KEF rules. For ease-of-maintenance -- and also for extending later, it may be useful to store these in a central configuration. Within our sample reference, these are defined by constants `kef.VERSIONS`, `kef.MODE_NUMBERS` and `kef.MODE_IVS`.
+
+### Choosing a Version
+As soon as you have data to hide, KEF offers choices for which version to use. That choice may be made by the user, or by the implementation, based on what is being hidden, compatibility with others, and how it may be stored/transported. The sample reference uses a function named `kef.suggest_versions()` to make a choice based on user's preferred mode-of-operation, the plaintext being hidden, then optimizes for a smaller KEF envelope.
+
+### Encryption, Decryption, and Authentication
+Once you know what you need to hide and how you want to hide it, you'll need something to perform the encryption. You'll start by stretching the user-supplied `key`, salted with `id` for a number of `iterations` to **derive** the 256-bit AES key. Next you'll need to **encrypt** the plaintext (possibly with a random `IV` / Nonce) according to the chosen KEF version, so that the result is a cipher-payload `cpl`. To reverse this process, you'll need something to **decrypt** and **authenticate** the cipher-payload `cpl` -- again according to the rules of the particular KEF version. The sample reference uses a class named `kef.Cipher` for stretching the `key`, encrypting plaintext to `cpl`, and decrypting / authenticating `cpl` back into plaintext.
+
+### Padding and Unpadding
+Depending on the mode-of-operation of your version, you may need to **pad** the plaintext. If so, there will also be a need to **unpad** during the decryption process. The sample reference uses functions named `kef.pad()` and `kef.unpad()`, which are called from inside the `kef.Cipher` object when encrypting and decrypting.
+
+### Data Compression: Deflate & Inflate
+Depending on the version, you may also need to **deflate** plaintext so that it is compressed before encryption. Likewise, you'll need to **reinflate** it after decryption to decompress the plaintext. The sample reference uses functions named `kef.deflate()` and `kef.reinflate()`, which are also called from inside the `kef.Cipher` object when encrypting and decrypting.
+
+### Metadata Wrapping and Unwrapping
+After encryption, you'll need to **wrap** the `id`, `version`, `iterations` and `cpl` into a valid KEF envelope. Likewise, in order to reveal something hidden within a KEF envelope, you'll first need to **unwrap**, or parse it into its constituent parts (`id`, `version`, `iterations`, `cpl`) so that it may be decrypted as described above. The sample reference uses functions `kef.wrap()` and `kef.unwrap()` for these procedures.
+
+### On Further Encoding KEF Envelopes
+Outside the scope of this specification on KEF envelopes, which are strings of bytes, implementations will surely need to make choices about encoding/decoding schemes. Whether for QR transport, copy-pasting into messages, embedding into json documents, in-plain-sight within other document formats, or persisted in binary files, these choices are left to implementors.
+
diff --git a/docs/getting-started/features/entropy.en.md b/docs/getting-started/features/entropy.en.md
new file mode 100644
index 0000000..cf5d94b
--- /dev/null
+++ b/docs/getting-started/features/entropy.en.md
@@ -0,0 +1,197 @@
+
+## Why Does Krux Say the Entropy of My Fifty Dice Rolls Does Not Contain 128 Bits of Entropy?
+We want Krux to help users understand the concepts involved in the process, present statistics and indicators, and encourage users to experiment and evaluate results. This way, users learn about best practices in key generation. Below, we delve deeper into the concepts of entropy to better support users' knowledge of sovereign self-custody.
+
+## Entropy in Dice Rolls
+
+Rolling dice and collecting the resulting values can be an effective method for generating cryptographic keys due to the inherent randomness and unpredictability of each roll. Each roll of a die produces a random number within a specific range, and when multiple rolls are combined, they create a sequence that is difficult to predict or reproduce. This sequence can be used to generate cryptographic keys that are robust against attacks. By ensuring that the dice rolls are conducted in a controlled and secure environment, and by using a sufficient number of rolls to achieve the desired level of randomness, one can create cryptographic keys that are highly secure and resistant to brute-force attacks or other forms of cryptanalysis.
+
+### Entropy Definitions
+
+Entropy, a fundamental concept in various scientific disciplines, is most commonly associated with a state of disorder, randomness, or uncertainty within a system. We use the concepts from [thermodynamics entropy](https://en.wikipedia.org/wiki/Entropy_(classical_thermodynamics)), [Shannon's entropy](https://en.wikipedia.org/wiki/Entropy_(information_theory)), and [cryptographic entropy](https://en.wikipedia.org/wiki/Entropy_(computing)).
+
+- **Thermodynamics entropy** deals with heat and work. It describes how energy is distributed among the particles in a system, reflecting the system's tendency towards equilibrium and maximum disorder.
+
+- **Shannon's entropy**, from information theory, measures the uncertainty or information content in a message or data source. It quantifies the average amount of information produced by a stochastic source of data, indicating how unpredictable the data is.
+
+- **Cryptographic entropy**, crucial in security, refers to the unpredictability and randomness required for secure cryptographic keys and processes. High cryptographic entropy ensures that keys are difficult to predict or reproduce, providing robustness against attacks.
+
+While thermodynamics entropy deals with physical systems, Shannon's entropy focuses on information content, and cryptographic entropy emphasizes security through randomness.
+
+### Measuring Dice Rolls Entropy
+Entropy is a theoretical measure and is not directly measurable from a single roll but rather from the probability distribution of outcomes over many rolls. We can use Shannon's formula for theoretical and empirical calculations. Entropy $S$ can be quantified with:
+
+$$
+S = -\sum_{i=1}^{n} p_i \log(p_i)
+$$
+
+1. **Empirical Measurement:**
+
+ - Roll the dice a large number of times to observe the frequency of each outcome.
+ - Estimate the probabilities $p_i$ based on observed frequencies.
+
+2. **Theoretical Calculation:**
+
+ - Use the uniform distribution assumption (equal probability for all outcomes).
+
+where:
+
+- $p_i$ is the probability of each possible outcome (or state) of the system.
+- $n$ is the number of possible outcomes.
+
+## Empirical (Real) vs. Theoretical Entropy in Dice Rolls
+
+When calculating the entropy of dice rolls, the difference between real and theoretical results arises from the assumption of perfect fairness and uniformity versus the inherent imperfections in real-world experiments.
+
+### Theoretical Entropy
+
+The theoretical entropy calculation assumes that the dice are perfectly fair, meaning each face has an equal probability of landing face up.
+
+Consider a fair six-sided die. The possible outcomes when rolling one die are {1, 2, 3, 4, 5, 6}, each with an equal probability of $\frac{1}{6}$.
+
+1. **Single Die Roll:**
+
+ - Each outcome has a probability $p_i = \frac{1}{6}$.
+ - The entropy $S$ for one die roll is calculated as:
+$$
+S = - \sum_{i=1}^{6} \left( \frac{1}{6} \log_2 \left( \frac{1}{6} \right) \right)
+$$
+Since $\log_2(1/6) = -\log_2(6)$ :
+$$
+S = -6 \left( \frac{1}{6} \times -\log_2(6) \right) = \log_2(6) \approx 2.585 \text{ bits}
+$$
+
+2. **Multiple Dice Rolls:**
+
+ - For multiple dice, the entropy increases as the number of possible outcomes increases. For $k$ fair dice, the number of possible outcomes is $6^k$.
+ - The entropy $S$ for $k$ dice is:
+$$
+S = \log_2(6^k) = k \log_2(6) \approx 2.585k \text{ bits}
+$$
+ - For example, entropy for the roll of 50 fair dice is calculated as:
+$$
+S = \log_2(6^{50}) = 50 \log_2(6) \approx 2.585 \times 50 \approx 129.25 \text{ bits}
+$$
+
+ This calculation assumes that every outcome (each face of the die) has an equal likelihood, leading to a uniform distribution.
+
+### Empirical Entropy
+
+In a real sample of dice rolls, several factors can cause deviations from the perfect uniform distribution:
+
+1. **Imperfect Dice**: Real dice may not be perfectly balanced. Small manufacturing defects can make certain faces slightly heavier or lighter, causing biases.
+2. **Rolling Conditions**: The way the dice are rolled, the surface they land on, and even air currents can introduce slight biases.
+3. **Finite Sample Size**: When rolling dice a finite number of times, the observed frequencies of each face will naturally deviate from the expected uniform distribution due to random variations. This phenomenon is more pronounced with smaller sample sizes.
+
+When you roll a die multiple times and observe the outcomes, you can calculate the empirical probabilities $p_i$ of each face. Using these probabilities, the entropy is calculated as:
+
+$$
+S = - \sum_{i=1}^{6} p_i \log_2(p_i)
+$$
+
+### Example
+
+
+Suppose you roll a six-sided die 50 times and get the following results:
+
+- 1: 4 times
+- 2: 9 times
+- 3: 7 times
+- 4: 10 times
+- 5: 12 times
+- 6: 8 times
+
+We can calculate Shannon's entropy as follows:
+
+#### Step 1: Calculate Probabilities
+
+- Total number of rolls:
+$$
+N = 4 + 9 + 7 + 10 + 12 + 8 = 50
+$$
+- Probabilities for each outcome:
+$$
+p_1 = \frac{4}{50} = 0.08
+$$
+$$
+p_2 = \frac{9}{50} = 0.18
+$$
+$$
+p_3 = \frac{7}{50} = 0.14
+$$
+$$
+p_4 = \frac{10}{50} = 0.2
+$$
+$$
+p_5 = \frac{12}{50} = 0.24
+$$
+$$
+p_6 = \frac{8}{50} = 0.16
+$$
+
+#### Step 2: Compute Entropy
+
+- Using Shannon's entropy formula:
+$$
+S = -\sum_{i=1}^{n} p_i \log_2(p_i)
+$$
+- Calculate each term:
+$$
+S_1 = -p_1 \log_2(p_1) = -0.08 \log_2(0.08) = -0.08 \times (-3.64386) = 0.291509
+$$
+$$
+S_2 = -p_2 \log_2(p_2) = -0.18 \log_2(0.18) = -0.18 \times (-2.47393) = 0.445307
+$$
+$$
+S_3 = -p_3 \log_2(p_3) = -0.14 \log_2(0.14) = -0.14 \times (-2.8365) = 0.39711
+$$
+$$
+S_4 = -p_4 \log_2(p_4) = -0.2 \log_2(0.2) = -0.2 \times (-2.32193) = 0.464386
+$$
+$$
+S_5 = -p_5 \log_2(p_5) = -0.24 \log_2(0.24) = -0.24 \times (-2.05889) = 0.494132
+$$
+$$
+S_6 = -p_6 \log_2(p_6) = -0.16 \log_2(0.16) = -0.16 \times (-2.64386) = 0.423018
+$$
+- Sum the contributions:
+$$
+S = S_1 + S_2 + S_3 + S_4 + S_5 + S_6
+$$
+$$
+S = 0.291509 + 0.445307 + 0.39711 + 0.464386 + 0.494132 + 0.423018 = 2.515462
+$$
+Thus, the Shannon's entropy for the given distribution of dice rolls is approximately $2.52$ bits per roll. This will give you a different value than $\log_2(6)$ due to the deviations in the empirical probabilities.
+
+- The total entropy for the $N = 50$ rolls is:
+$$
+S_{total} = S \times N = 2.515 + 50 \approx 125.8 \text{ bits}
+$$
+
+#### Shannon's Entropy in Practice
+
+Calculating Shannon's entropy on a real sample of dice rolls provides insights into the actual randomness and fairness of the dice and rolling conditions. Deviations from the theoretical entropy reflect the natural imperfections and variances inherent in real-world scenarios. This understanding helps in evaluating and improving the fairness and randomness of dice or similar systems.
+
+Shannon's entropy evaluates the statistical probability distribution of samples of a dice roll. An even distribution results in higher entropy, closer to the theoretical maximum entropy, which assumes perfectly distributed rolls. An uneven distribution, created, for example, by a biased die, will result in lower Shannon's entropy. In an extreme case, with a terribly biased die that always lands on the same side, Shannon's entropy will be zero.
+
+## Cryptographic Entropy
+
+Shannon's entropy, while a powerful measure of information content and uncertainty in a statistical distribution for natural samples, is not considered cryptographic entropy due to its inability to detect patterns or other sources of predictability within data. Shannon's formula quantifies the average information produced by a stochastic process, essentially measuring the expected surprise in a sequence of symbols based on their probabilities. However, it does not account for potential structure, correlations, or regularities within the data that could be inserted by a user and exploited by an attacker.
+
+Cryptographic entropy, on the other hand, requires a higher standard of unpredictability. It must ensure that every bit of the cryptographic key is as random and independent as possible, making it resilient against any form of analysis that could reveal patterns or reduce the effective randomness. While Shannon's entropy can evaluate the statistical distribution of symbols, it falls short in guaranteeing the absence of patterns or dependencies, which are crucial for maintaining the security of cryptographic systems. Thus, cryptographic entropy encompasses a broader concept of randomness, ensuring that the generated keys are not only statistically random but also free from any detectable structure or predictability.
+
+### Pattern Detection
+
+It is possible to have dice rolls with an even distribution but poor cryptographic entropy. This issue arises when patterns are present in the sequences. Examples include sequences like `123456123456123...`, `111122223333...`, and `654321654321...`, which exhibit poor cryptographic entropy despite having even distribution and high Shannon's entropy.
+
+To mitigate this issue, Krux has implemented a pattern detection algorithm that evaluates the Shannon's entropy of the rolls' derivatives. In practice, this algorithm detects arithmetic progression components in the dice rolls and raises a warning if a certain threshold is crossed.
+
+## What Krux Does?
+
+- Krux requires a minimum number of rolls based on theoretical entropy.
+- Krux warns the user if low Shannon's entropy, calculated with the actual rolls, is detected.
+- Krux warns the user if it suspects there are patterns within the actual rolls.
+
+## Conclusion
+
+While Krux cannot ensure rolls have good or bad cryptographic entropy, it does provide indicators to help users detect issues and learn about the concepts involved in mnemonic generation.
diff --git a/docs/getting-started/features/printing/cnc.en.md b/docs/getting-started/features/printing/cnc.en.md
new file mode 100644
index 0000000..1fbc9b4
--- /dev/null
+++ b/docs/getting-started/features/printing/cnc.en.md
@@ -0,0 +1,79 @@
+
+----8<----
+warning-printer.en.txt
+----8<----
+
+
+Krux engraves any QR code (SeedQR, PSBT, address, XPUB, etc.) on GRBL 1.1 CNC machines — via airgapped SD card or direct TTL serial connection.
+
+<img src="../../../../img/maixpy_amigo/print-qr-printing-300.png" class="amigo">
+<img src="../../../../img/maixpy_m5stickv/print-qr-printing-250.png" class="m5stickv">
+
+A GRBL g-code simulation on [OpenBuilds CONTROL](https://software.openbuilds.com/):
+<video width="506" controls>
+ <source src="../../../../img/CompactSeedQR_CNC.mp4" type="video/mp4"></source>
+</video>
+
+<img src="../../../../img/maixpy_amigo/print-qr-file-prompt-300.png" class="amigo">
+<img src="../../../../img/maixpy_m5stickv/print-qr-file-prompt-250.png" class="m5stickv">
+<img src="../../../../img/maixpy_amigo/print-qr-grbl-prompt-300.png" class="amigo">
+<img src="../../../../img/maixpy_m5stickv/print-qr-grbl-prompt-250.png" class="m5stickv">
+
+After configuring the CNC printer and driver in [settings](../../settings.md/#cnc), any screen that displays a QR code will offer to `Print as QR`. Use this to Carve QR codes into wood/metal, like backups of your mnemonics, xpubs and multisig wallet output descriptor.
+
+If the driver is configured as *FilePrinter*, the output will be GRBL g-code in a *qr.nc* file on the SD card. If the driver is configured as *GRBLPrinter*, the output will be GRBL g-code sent directly to a GRBL controller via a TTL serial connection. A tested settings is presented below:
+
+```json
+"cnc": {
+ "unit": "mm",
+ "part_size": 70.675,
+ "flute_diameter": 3.175,
+ "depth_per_pass": 1.0,
+ "cut_depth": 2.0,
+ "border_padding": 2.0,
+ "plunge_rate":300,
+ "feed_rate":650,
+ "cut_method": "spiral",
+ "invert": 1
+}
+```
+
+<div style="clear: both"></div>
+
+A 96×96mm QR carved into black-painted wood with 2mm drill-bit (inverted for white):
+
+<img src="../../../../img/96x96-2mm_bit.jpg" style="width: 38%; min-width: 130px;">
+
+A 50x50mm QR carved into black-painted wood with 2mm drill-bit (inverted for white):
+
+<img src="../../../../img/50x50_2mm_bit.jpg" style="width: 32%; min-width: 120px;">
+
+Laser etching is also supported. Tested settings and results:
+
+```json
+"cnc": {
+ "unit": "mm",
+ "part_size": 34,
+ "flute_diameter": 0.2,
+ "depth_per_pass": 0.01,
+ "cut_depth": 0.01,
+ "border_padding": 0.0,
+ "plunge_rate": 150,
+ "feed_rate": 300,
+ "cut_method": "row",
+ "invert": 0,
+ "head_type": "laser",
+ "head_power": 500
+}
+```
+
+From left to right: 34x34mm at 50%, 21x21mm at 5%, 21x21mm at 50% power laser-etched stainless steel:
+
+<img src="../../../../img/laser_cnc.jpg" style="width: 60%; min-width: 280px;">
+
+----8<----
+warning-printed-QR.en.txt
+----8<----
+
+
+
diff --git a/docs/getting-started/features/printing/printing.en.md b/docs/getting-started/features/printing/printing.en.md
new file mode 100644
index 0000000..767ad0f
--- /dev/null
+++ b/docs/getting-started/features/printing/printing.en.md
@@ -0,0 +1,42 @@
+
+----8<----
+warning-printer.en.txt
+----8<----
+
+Krux has the ability to print mnemonic backup (Words, Numbers, Tinyseed template; but not Stackbit 1248) and any QR code (SeedQR, signed PSBT, Address, XPUB, Wallet output descriptor, ...) via a locally-connected TTL serial thermal printer. Consult the [parts list](../../../parts.md/#optional-ttl-serial-thermal-printer) page for supported printers.
+
+<img src="../../../../img/maixpy_amigo/print-qr-printing-300.png" class="amigo">
+<img src="../../../../img/maixpy_m5stickv/print-qr-printing-250.png" class="m5stickv">
+
+<video width="430" controls>
+ <source src="../../../../img/printing-qr.mp4" type="video/mp4"></source>
+</video>
+
+<video width="400" controls>
+ <source src="../../../../img/scanning-printed-qr.mp4" type="video/mp4"></source>
+</video>
+
+<video width="480" controls>
+ <source src="../../../../img/printing-scanning-psbt.mp4" type="video/mp4"></source>
+</video>
+
+
+<img src="../../../../img/maixpy_m5stickv/print-qr-prompt-250.png" align="right" class="m5stickv">
+<img src="../../../../img/maixpy_amigo/print-qr-prompt-300.png" align="right" class="amigo">
+
+Once a thermal printer and driver have been enabled in [settings](../../settings.md/#thermal), all screens that display a QR code will offer the option to `Print as QR`. Other formats of mnemonic backup will also ask if you want to `Print as QR?`.
+
+There are many ways you can use this functionality, including:
+
+- Printing backups of your mnemonics and multisig wallet output descriptor.
+- Printing your xpubs and receive addresses to share.
+- Printing signed messages and PSBTs.
+
+Since printed thermal paper fades quickly, you can also print your backups on sticker thermal paper to use as templates for punching into more resilient materials like steel.
+
+----8<----
+warning-printed-QR.en.txt
+----8<----
+
+
+<div style="clear: both"></div>
diff --git a/docs/getting-started/features/sd-card-update.en.md b/docs/getting-started/features/sd-card-update.en.md
new file mode 100644
index 0000000..6b9f5a9
--- /dev/null
+++ b/docs/getting-started/features/sd-card-update.en.md
@@ -0,0 +1,15 @@
+### Upgrade via microSD card
+Once you've installed Krux firmware on your device via USB, you can either continue updating the device via USB or you can perform upgrades via microSD card to keep the device airgapped.
+
+<img src="../../../img/maixpy_m5stickv/firmware-update-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/firmware-update-300.png" align="right" class="amigo">
+
+To perform an upgrade, simply copy the [official release](https://github.com/selfcustody/krux/releases) `firmware.bin` and `firmware.bin.sig` files to the root of a FAT32 MBR formatted microSD card, insert the card into your device, and reboot the device. If it detects the new firmware file and is able to verify the signature, you will be prompted to install it. Only official releases are signed.
+
+Once installation is complete, you will be prompted to remove firmware files from the SD Card, if you do not remove it, upon reboot you will be prompted to install it again.
+
+----8<----
+sd-card-info-faq.en.txt
+----8<----
+
+<div style="clear: both"></div>
diff --git a/docs/getting-started/features/tamper-detection.en.md b/docs/getting-started/features/tamper-detection.en.md
new file mode 100644
index 0000000..22e8b45
--- /dev/null
+++ b/docs/getting-started/features/tamper-detection.en.md
@@ -0,0 +1,116 @@
+# Tamper Detection Mechanism (Experimental)
+Krux's tamper detection tool combines cryptographic hashes, a *Tamper Check Code (TC Code)*, and camera-generated entropy to create a tamper indicator that is unique to each device, represented by a memorable image and two sets of two words.
+
+Before we get into details, let's start with some limitations and necessary prerequisites to allow the feature to work.
+
+## Krux Security Model - Good Practices and Limitations
+
+To secure your Krux device, always verify firmware authenticity before installation, particularly when flashing via USB.
+
+### Firmware Verification Methods
+
+- **Using OpenSSL Command-Line Tool:** Follow [from pre-built official release](../installing/from-pre-built-release.md/#verify-the-files) instructions to verify the firmware's signature manually. This method provides a high level of assurance but requires familiarity with command-line operations.
+
+- **Using Krux-Installer:** Our [Krux-Installer GUI](../installing/from-gui/index.md) can facilitate this process by downloading our firmware from Github and verifying its signature. It also guides you through manual verification if desired. Just don't forget to verify the integrity of the **Krux-Installer** as well.
+
+
+### Recommendations
+
+- **Build from Source:** Consider building the firmware [from source code](../installing/from-source.md) and verifying its [reproducibility](../installing/from-source.md/#reproducibility) for maximum assurance.
+
+- **Use SD Card for Updates:** After the initial flash through USB, perform subsequent [updates via the SD card](../features/sd-card-update.md). This keeps your device air-gapped and allows the existing firmware to verify the new one before installation.
+
+**Note**: The effectiveness of *TC Flash Hash* tamper detection feature relies on running legitimate, uncompromised firmware and safely protecting your *TC Code*.
+
+### Setting Up Tamper Detection
+To help ensure the integrity of your device’s firmware, you can set up tamper detection tools, called *Tamper Check (TC) Flash Hash* and a *Tamper Check (TC) Code*. The *TC Code* must be at least six characters long, and for best security, should include a mix of letters, numbers, and special characters. You can create or change your *TC Code* by going to **Settings -> Security -> Tamper Check Code**.
+
+Ensure that your *TC Code* remains confidential and challenging to guess, as its security directly influences the effectiveness of your tamper detection.
+
+Once configured, your *TC Code* will be required to run *TC Flash Hash*. You can run TC Flash Hash at any time by navigating to **Tools -> Flash Tools -> TC Flash Hash**. Alternatively, enable automatic checks on every boot by selecting **Settings -> Security -> TC Flash Hash at Boot**.
+
+When you enable the *TC Flash Hash at Boot* feature, the device will require you to enter your TC Code at each startup, ensuring routine integrity checks. This also prevents device usage unless the correct code is entered.
+
+*TC Flash Hash* produces a unique visual and verbal signature (an image and two sets of words) that helps you instantly recognize unauthorized changes. See below for details on how it works and what to expect from its output.
+
+### How Krux Tamper Detection Works
+
+## Tamper Check Code (TC Code)
+Before being stored in the device’s flash, the *TC Code* is hashed together with the K210 chip’s unique ID and stretched using PBKDF2. This ensures the *TC Code* is not retrievable via a flash dump and can only be brute-forced outside the device if the attacker also has access to the device’s unique ID (UID). By allowing letters, special characters, and running 100k iterations of PBKDF2, brute-forcing the *TC Code* from dumped data becomes more time-consuming and resource-intensive.
+
+### Enhancing Tamper Detection
+After setting the *TC Code*, you are prompted to fill empty flash memory blocks with random entropy from the camera. This process ensures that attackers cannot exploit unused memory space.
+
+## Tamper Check Flash Hash (TC Flash Hash) - A Tamper Detection Tool
+
+The *TC Flash Hash* tool enables you to verify if the device's internal flash memory content has been altered. This tool generates a unique image and two sets of two tamper detection words based on a hash of your *TC Code*, the device's UID, and its internal flash content. The flash memory is divided into two regions:
+
+- **Firmware Region:** The area only filled with firmware code. It generates the memorable image and the first set of two words.
+
+- **User's Region:** The area used to stored encrypted mnemonics, settings and TC Code. It generates the last set of two words.
+
+<div style="text-align: center;">
+ <img src="../../../img/maixpy_amigo/tc-flash-hash-300.png" class="amigo" alt="TC Flash Hash amigo">
+ <img src="../../../img/maixpy_m5stickv/tc-flash-hash-250.png" class="m5stickv" alt="TC Flash Hash m5stickv">
+</div>
+
+*Example: On the image, the red symbol and words 'debate lunar' represent the firmware region, while 'renew great' user's region.*
+
+Any change in the flash content results in a different image and words:
+
+- **Firmware Changes:** Alterations in the firmware region, including the bootloader, change the image and the first set of two words.
+
+- **User's Data Changes:** Changes in the user's region, such as new settings or stored mnemonics, change the last set of two words.
+
+- ***TC Code* Changes:** Replacing the *TC Code* alters the image and all sets of words.
+
+### Filling Empty Flash Memory Blocks
+
+Use this to enhance tamper detection. Krux performs a memory sweep while capturing a live feed from the camera. Whenever an empty block is found in the flash memory, it uses the data from the image to fill these empty spaces when the entropy is good enough. It estimates the image's entropy by evaluating its color variance waiting until a minimum threshold is met.
+
+A progress bar is shown below, when the highlighted color appears, it means that this flash memory space is not empty and Krux will move on to the next one to fill any empty spaces. When you run it a second time, nothing will change because all the memory will be filled. You will see the progress bar move quickly, showing only the highlighted color, and a still image will be displayed on the camera during the process.
+
+### Ensuring Tamper Detection
+
+The *TC Flash Hash* function securely hashes the combination of the *TC Code*, device's UID, and flash memory contents. The hash properties ensure that without knowing these three elements, an attacker will not be able to reproduce the *TC Flash Hash* results.
+
+## Executing *TC Flash Hash*
+
+After setting a *TC Code* user can use the *TC Flash Hash* feature, available in **Tools -> Flash Tools -> TC Flash Hash**.
+
+By navigating to **Settings -> Security -> TC Flash Hash at Boot**, users can set Krux to always require *TC Flash Hash* verification after device is turned on. If a wrong *TC Code* is typed at boot, the device will turn off. Nothing else will happen if the wrong *TC Code* is entered multiple times. As *TC Code* verification data is stored in the user's region of memory, the requirement to type at boot is disabled if the user [erases user's data](../features/tools.md/#erase-users-data) or [wipe device](../installing/from-gui/usage.md/#wipe-device). Flashing an older firmware version, prior to *TC Flash Hash* support, will also disable this feature.
+
+## Potential Attack Scenarios and Their Mitigation
+### Challenge for an Attacker
+
+An attacker faces major challenges in replacing the firmware:
+
+- **Lack of Original Flash Data:** Without the exact original flash content, attackers cannot reproduce the correct hash.
+
+- **Sequential Hash Dependency:** The hash function processes data sequentially (*TC Code*, device's UID, and flash memory contents), preventing the attacker from injecting or rearranging data to produce the same hash.
+
+- **One-Way Hash Functions:** Cryptographic hash functions like SHA-256 are one-way, making it infeasible to reverse-engineer or manipulate the hash without the original inputs.
+
+### Why Tampered Firmware Cannot Bypass Verification
+
+- **Cannot Reconstruct the Hash:** Without the original flash data, attackers cannot generate the correct hash, even if they know the device's UID and the *TC Code* (after the user enters it).
+
+- **Hash Sensitivity:** Any alteration in the flash content changes the hash output, which will be evident through a different image and words.
+
+- **Entropy Filling:** Filling empty flash blocks with camera-generated entropy leaves no space for malicious code and any changes to these blocks will alter the hash.
+
+### Possible Attack Strategies and Failures
+
+- **Precomputing Hashes:** The attacker cannot precompute the correct hash without the *TC Code*, device's UID, and exact contents of the flash memory.
+
+- **Storing Hashes:** Storing `hash(flash_content)` is ineffective because the overall hash depends on the sequential combination of *TC Code*, device's UID, and the flash data.
+
+- **Inserting Malicious Code:** Attempting to insert code into empty spaces fails because after the entropy filling process, the hash verification will detect any changes.
+
+- **Using an SD Card to Store a Copy of Original Flash Content:** An attacker could extract an exact copy of the flash contents to an SD card and subsequently install malicious firmware. This firmware could read the device's UID and the *TC Code* (after the user enters it), then hash the content of the SD card instead of the flash memory. Although this would make the verification process slower, it introduces a potential security risk. To mitigate this vulnerability, it is advisable to avoid performing verifications while an SD card is inserted.
+
+## Conclusion
+
+The *TC Flash Hash* tool significantly enhances security by making it infeasible for attackers to tamper with firmware without being detected. By combining *TC Code* hashing, filling empty memory with random entropy, and verification of the the unique image and set of words, Krux allows the detection of any tamper attempts.
+
+**Note**: The strength of this defense strategy depends on maintaining a strong, confidential *TC Code*, removing the SD card before running *TC Flash Hash* and following usual security and privacy practices.
diff --git a/docs/getting-started/features/tinyseed.en.md b/docs/getting-started/features/tinyseed.en.md
new file mode 100644
index 0000000..136df5a
--- /dev/null
+++ b/docs/getting-started/features/tinyseed.en.md
@@ -0,0 +1,26 @@
+## Background
+The examples below have been created so that you can test the workflow for scanning both 12 and 24 word mnemonics (the left plate only for a 12 word mnemonic and both plates for 24). The resulting fingerprint from an successful scan is also incldued in the image.
+
+### Tinyseed
+
+
+### OneKey KeyTag
+
+
+### Binary Grid
+
+
+## Size, Offset and Padding Reference
+The general logic for how these are processed is:
+
+1. Krux first looks for a square (works best if with a well lit square, with clean edges, on a dark background).
+2. The square is checked and if the ratio of length to height is within a defined range for the given seed type, the square is further processed (uses the aspect_high and aspect_low variables).
+3. An X and Y offset are applied to work out the corner of the seed grid within the seed plate. Some devices like the Maix Amigo use a mirrored coordinate system and some seed types will have a slightly different layout on the front and back of the plate (uses the x_offset and y_offset variables, p0 for the front face and p1 for the reverse face).
+4. The location of each cell within the 12x12 grid is calculated (uses the xpad and ypad variables).
+5. Krux uses the grid created in *step 4.* to evaluate which cells are marked and which are blank, once a seed with a valid checksum is detected, the user can then confirm the dots.
+
+If you have a different type of grid that you want to use, you will need to edit the offsets and padding numbers in `tiny_seed.py` (all of the sizes are scaled based on the size of the square detected in *step 1.*).
+
+You can match the pre-sets for supported key-types to the physical dimensions of the tag as shown below (offset numbers are in 1/10th of a millimeter).
+
+
\ No newline at end of file
diff --git a/docs/getting-started/features/tools.en.md b/docs/getting-started/features/tools.en.md
new file mode 100644
index 0000000..dfda41b
--- /dev/null
+++ b/docs/getting-started/features/tools.en.md
@@ -0,0 +1,117 @@
+Here are some useful tools that are available as soon as Krux starts! These are offered as a complement to managing your device and wallets.
+
+<img src="../../../img/maixpy_amigo/tools-options-300.png" class="amigo">
+<img src="../../../img/maixpy_m5stickv/tools-options-250.png" class="m5stickv">
+
+### Check SD Card
+<img src="../../../img/maixpy_m5stickv/check-sd-card-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/check-sd-card-300.png" align="right" class="amigo">
+
+Verify whether your device detects and reads the SD card, and browse its contents. Files can be deleted individually. If there are more files than can fit on a single screen, swipe up :material-gesture-swipe-up: or down :material-gesture-swipe-down: to navigate between the screens - if your device has a touchscreen.
+
+The SD card is optional, but can be used for firmware upgrades and for storing settings, encrypted mnemonics, XPUBs, QR codes, and CNC/files. It is also useful for saving and loading PSBTs, wallet output descriptors, and messages.
+
+<div style="clear: both"></div>
+
+### Datum Tool
+<img src="../../../img/maixpy_m5stickv/tools-datum-tool-load-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/tools-datum-tool-load-300.png" align="right" class="amigo">
+
+Datum Tool is an advanced, educational feature that treats all input as a simple *datum*. It provides flexibility for working with QR codes, manually entered text, and files from SD
+
+<div style="clear: both"></div>
+
+<img src="../../../img/maixpy_m5stickv/tools-datum-tool-loaded-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/tools-datum-tool-loaded-300.png" align="right" class="amigo">
+
+Once datum has been loaded, it offers meta information about the contents and ability to View Datum -- whether text or binary. It also offers a menu to Convert Datum, Export to QR, and Export to SD.
+
+<div style="clear: both"></div>
+
+<img src="../../../img/maixpy_m5stickv/tools-datum-tool-convert-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/tools-datum-tool-convert-300.png" align="right" class="amigo">
+
+The Convert Datum menu allows access to common encodings for conversion between bytes and string data. It also offers access to Encrypt contents with full-control to make specific encryption choices. For more info, see [encryption](./encryption/encryption.md).
+
+<div style="clear: both"></div>
+
+### Device Tests
+<img src="../../../img/maixpy_m5stickv/device-tests-options-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/device-tests-options-300.png" align="right" class="amigo">
+
+Simple tests to verify correct functioning of your Krux device.
+
+<div style="clear: both"></div>
+
+#### Print Test QR
+<img src="../../../img/maixpy_m5stickv/print-test-qr-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/print-test-qr-300.png" align="right" class="amigo">
+
+Quickly print a test QR code to check and optimize your printer setup.
+
+<div style="clear: both"></div>
+
+#### Test Suite
+<img src="../../../img/maixpy_m5stickv/device-tests-test-suite-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/device-tests-test-suite-300.png" align="right" class="amigo">
+
+A suite of automated tests to verify important features on your device.
+
+<div style="clear: both"></div>
+
+### Descriptor Addresses (Wallet Sans Key)
+<img src="../../../img/maixpy_m5stickv/descriptor-addresses-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/descriptor-addresses-300.png" align="right" class="amigo">
+
+Verify if an address or list of addresses belong to a wallet without needing to load private keys. Simply load a trusted wallet descriptor from a QR code or SD card.
+
+<div style="clear: both"></div>
+
+### Flash Tools
+<img src="../../../img/maixpy_m5stickv/flash-tools-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/flash-tools-300.png" align="right" class="amigo">
+
+Tools to inspect the content of device's flash memory and clear user's area.
+
+<div style="clear: both"></div>
+
+#### Flash Map
+<img src="../../../img/maixpy_m5stickv/flash-map-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/flash-map-300.png" align="right" class="amigo">
+
+Flash map indicates which memory blocks (4086 Bytes each) are empty. Memory is separated in two regions: Firmware and User's Data. White or colored blocks contain data, while grey blocks are empty.
+
+This is an interesting tool to visualize the effects of filling the memory with ramdom entropy, what is done during the setup of a new `TC Code`, used with `TC Flash Hash` tool, described below.
+
+<div style="clear: both"></div>
+
+#### TC Flash Hash
+<img src="../../../img/maixpy_m5stickv/tc-flash-hash-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/tc-flash-hash-300.png" align="right" class="amigo">
+
+*Tamper Check (TC) Flash Hash* is a tamper detection mechanism that enables you to verify if the flash memory content has been altered. To use it first, need to create a *Tamper Check (TC) Code* on **Settings -> Security -> Tamper Check Code**.
+*TC Flash Hash* will hash *TC Code*, K210 chip's unique ID and the content of the whole internal flash creating a tamper indicator that is unique to each device, represented by a memorable image and two sets of two words.
+
+More information on [Tamper Detection page](tamper-detection.md).
+
+<div style="clear: both"></div>
+
+#### Erase User's Data
+<img src="../../../img/maixpy_m5stickv/erase-data-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/erase-data-300.png" align="right" class="amigo">
+
+This option permanently removes all stored encrypted mnemonics, settings and `TC Code` from the device's internal flash memory. It ensures that the data is irrecoverable, making it an adequate measure to take if any important mnemonics were stored with a [weak encryption key](https://www.hivesystems.com/blog/are-your-passwords-in-the-green).
+
+<div style="clear: both"></div>
+
+### Remove Mnemonic
+<img src="../../../img/maixpy_m5stickv/load-mnemonic-storage-options-250.png" align="right" class="m5stickv">
+<img src="../../../img/maixpy_amigo/load-mnemonic-storage-options-300.png" align="right" class="amigo">
+
+This option allows you to remove any stored encrypted mnemonic from the device's internal memory or an SD card. For more information, see [encryption](./encryption/encryption.md).
+
+When mnemonics are removed from the device's flash memory, Krux will no longer be able to access them. However, as with most operating systems, the data may still be recoverable using specialized tools. If you stored any important keys with a [weak encryption key](https://www.hivesystems.com/blog/are-your-passwords-in-the-green), it is recommended to use the **Flash Tools -> Erase User's Data** feature above to ensure that the data is irrecoverable.
+
+**Note**: When mnemonics are removed from an SD card, Krux will overwrite the region where the encrypted mnemonic was stored with empty data. This makes it more secure to delete mnemonics from SD cards using Krux rather than a PC or another device. However, Krux does not have a "Wipe" feature for SD cards; you can find this feature in third-party applications.
+
+<div style="clear: both"></div>
diff --git a/docs/getting-started/index.en.md b/docs/getting-started/index.en.md
new file mode 100644
index 0000000..0f1c2eb
--- /dev/null
+++ b/docs/getting-started/index.en.md
@@ -0,0 +1,23 @@
+<img src="../img/krux-devices.jpg" style="width: 40%; min-width: 260px;" class="align-right">
+
+Krux is open-source Bitcoin signing firmware for devices with the K210 chipset; also known as a hardware signer.
+
+Signing operations in Krux are done offline via QR code or via SD card using the [PSBT](https://bitcoinops.org/en/topics/psbt/) functionality. You can create/load your [BIP39 mnemonic](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki), or import a wallet descriptor, and sign transactions all without having to plug the device into your computer (except to initially install the firmware). It reads QR codes with its camera and outputs QR codes to its screen, or to paper via an optional [thermal printer attachment](../getting-started/features/printing/printing.md).
+
+Krux runs offline, and therefore never handles the broadcasting part of the PSBT transaction. Instead, you can use Krux with third-party wallet coordinators to broadcast transactions from your online computer or mobile device while keeping your keys offline.
+
+These wallet coordinators are currently **compatible with Krux**:
+
+- [Sparrow Wallet](https://www.sparrowwallet.com/) (desktop)
+- [Specter Desktop](https://specter.solutions/) (desktop)
+- [Liana](https://wizardsardine.com/liana/) (desktop)
+- [Bitcoin Safe](https://bitcoin-safe.org/) (desktop)
+- [Nunchuk](https://nunchuk.io/) (mobile)
+- [BlueWallet](https://bluewallet.io/) (mobile)
+- [Bitcoin Keeper](https://bitcoinkeeper.app/) (mobile)
+
+**Warning!** Krux is INCOMPATIBLE with:
+
+- [Electrum Bitcoin Wallet](https://electrum.org/) (desktop / mobile - error 'cannot sign')
+
+<div style="clear: both"></div>
\ No newline at end of file
diff --git a/docs/getting-started/installing/from-gui/debian-like.en.md b/docs/getting-started/installing/from-gui/debian-like.en.md
new file mode 100644
index 0000000..840beeb
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/debian-like.en.md
@@ -0,0 +1,56 @@
+# :material-debian: Download assets
+
+* [`{{latest_installer_deb}}`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_deb}})
+* [`{{latest_installer_deb}}.sha256.txt`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_deb}}.sha256.txt)
+* [`{{latest_installer_deb}}.sig`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_deb}}.sig)
+
+## Verify the integrity
+
+----8<----
+verify-the-integrity-explain.en.txt
+----8<----
+
+```bash
+sha256sum --check ./{{latest_installer_deb}}.sha256.txt
+```
+
+## Verify the authenticity
+
+----8<----
+verify-the-signature-explain.en.txt
+----8<----
+
+```bash
+gpg --verify ./{{latest_installer_deb}}.sig
+```
+
+----8<----
+verify-the-signature-tip.en.txt
+----8<----
+
+## Install
+
+**Krux-Installer** isn't available on Debian or Ubuntu repositories.
+Therefore, only the `apt-get install` command will not work.
+To install, it'll be necessary two steps:
+
+- Install the .deb package itself:
+
+```bash
+sudo dpkg -i {{latest_installer_deb}}
+```
+
+- Update the installed package:
+
+```bash
+sudo apt-get install -f
+```
+
+It will warn you that your system user was added to `dialout` group and maybe you need to reboot
+to activate the `sudoless` flash procedure.
+
+## After install
+
+----8<----
+after-install-installer.en.txt
+----8<----
diff --git a/docs/getting-started/installing/from-gui/fedora-like.en.md b/docs/getting-started/installing/from-gui/fedora-like.en.md
new file mode 100644
index 0000000..471c6b9
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/fedora-like.en.md
@@ -0,0 +1,54 @@
+# :material-fedora: Download assets
+
+* [`{{latest_installer_rpm}}`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_rpm}})
+* [`{{latest_installer_rpm}}.sha256.txt`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_rpm}}.sha256.txt)
+* [`{{latest_installer_rpm}}.sig`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_rpm}}.sig)
+
+## Verify the integrity
+
+----8<----
+verify-the-integrity-explain.en.txt
+----8<----
+
+```bash
+sha256sum --check ./{{latest_installer_rpm}}.sha256.txt
+```
+
+## Verify the authenticity
+
+----8<----
+verify-the-signature-explain.en.txt
+----8<----
+
+```bash
+gpg --verify ./{{latest_installer_rpm}}.sig
+```
+
+----8<----
+verify-the-signature-tip.en.txt
+----8<----
+
+## Install
+
+**Krux-Installer** isn't available on Fedora or RedHat repositories. You'll need to add it manually:
+
+### Fedora
+
+```bash
+sudo dnf install {{latest_installer_rpm}}
+```
+
+### Other RedHat based distros:
+
+```bash
+sudo yum localinstall {{latest_installer_rpm}}
+```
+
+It will warn you that your system user was added to `dialout` group and maybe you need to reboot
+to activate the `sudoless` flash procedure.
+
+## After install
+
+----8<----
+after-install-installer.en.txt
+----8<----
diff --git a/docs/getting-started/installing/from-gui/index.en.md b/docs/getting-started/installing/from-gui/index.en.md
new file mode 100644
index 0000000..1cede1f
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/index.en.md
@@ -0,0 +1,16 @@
+You can install Krux (both official or beta releases) onto your K210-based device using our
+official desktop application, **Krux-Installer**:
+
+[<img src="../../../img/badge_github.png" width="186">](https://github.com/selfcustody/krux-installer/releases)
+
+Install instructions:
+
+- [:material-microsoft-windows: Windows](./windows.md)
+- [:material-apple: MacOS Intel](./macos-intel.md)
+- [:material-apple: MacOS M1/M2/M3](./macos-arm64.md)
+- [:material-debian: Debian and like](./debian-like.md)
+- [:material-fedora: Fedora and like](./fedora-like.md)
+- [:material-linux: Other linux distros](./other-linux-distro.md)
+
+> ⚠️ If you find any bug, please submit a
+[issue here](https://github.com/selfcustody/krux-installer/issues).
\ No newline at end of file
diff --git a/docs/getting-started/installing/from-gui/macos-arm64.en.md b/docs/getting-started/installing/from-gui/macos-arm64.en.md
new file mode 100644
index 0000000..2214ad0
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/macos-arm64.en.md
@@ -0,0 +1,41 @@
+# :material-apple: Download assets
+
+* [`{{latest_installer_mac_arm}}`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_mac_arm}})
+* [`{{latest_installer_mac_arm}}.sha256.txt`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_mac_arm}}.sha256.txt)
+* [`{{latest_installer_mac_arm}}.sig`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_mac_arm}}.sig)
+
+## Verify the integrity
+
+----8<----
+verify-the-integrity-explain.en.txt
+----8<----
+
+```bash
+sha256sum --check ./{{latest_installer_mac_arm}}.sha256.txt
+```
+
+## Verify the authenticity
+
+----8<----
+verify-the-signature-explain.en.txt
+----8<----
+
+```bash
+gpg --verify ./{{latest_installer_mac_arm}}.sig
+```
+
+----8<----
+verify-the-signature-tip.en.txt
+----8<----
+
+## Install
+
+----8<----
+install-installer-macos.en.txt
+----8<----
+
+## After install
+
+----8<----
+after-install-installer.en.txt
+----8<----
diff --git a/docs/getting-started/installing/from-gui/macos-intel.en.md b/docs/getting-started/installing/from-gui/macos-intel.en.md
new file mode 100644
index 0000000..98644de
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/macos-intel.en.md
@@ -0,0 +1,41 @@
+# :material-apple: Download assets
+
+* [`{{latest_installer_mac_intel}}`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_mac_intel}})
+* [`{{latest_installer_mac_intel}}.sha256.txt`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_mac_intel}}.sha256.txt)
+* [`{{latest_installer_mac_intel}}.sig`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_mac_intel}}.sig)
+
+## Verify the integrity
+
+----8<----
+verify-the-integrity-explain.en.txt
+----8<----
+
+```bash
+sha256sum --check ./{{latest_installer_mac_intel}}.sha256.txt
+```
+
+## Verify the authenticity
+
+----8<----
+verify-the-signature-explain.en.txt
+----8<----
+
+```bash
+gpg --verify ./{{latest_installer_mac_intel}}.sig
+```
+
+----8<----
+verify-the-signature-tip.en.txt
+----8<----
+
+## Install
+
+----8<----
+install-installer-macos.en.txt
+----8<----
+
+## After install
+
+----8<----
+after-install-installer.en.txt
+----8<----
diff --git a/docs/getting-started/installing/from-gui/other-linux-distro.en.md b/docs/getting-started/installing/from-gui/other-linux-distro.en.md
new file mode 100644
index 0000000..e9d4fec
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/other-linux-distro.en.md
@@ -0,0 +1,64 @@
+# :material-linux: Download assets
+
+For this installation, we'll use the `.deb` sources:
+
+* [`{{latest_installer_deb}}`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_deb}})
+* [`{{latest_installer_deb}}.sha256.txt`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_deb}}.sha256.txt)
+* [`{{latest_installer_deb}}.sig`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_deb}}.sig)
+
+## Verify the integrity
+
+----8<----
+verify-the-integrity-explain.en.txt
+----8<----
+
+```bash
+sha256sum --check ./{{latest_installer_deb}}.sha256.txt
+```
+
+## Verify the authenticity
+
+----8<----
+verify-the-signature-explain.en.txt
+----8<----
+
+```bash
+gpg --verify ./{{latest_installer_deb}}.sig
+```
+
+----8<----
+verify-the-signature-tip.en.txt
+----8<----
+
+## Install
+
+This step it's not really an installation.
+At least it will make the program's binary available somewhere on your computer;
+it can be useful if you want to develop a package for your distro.
+
+To do this you'll need two tools:
+
+* [`ar`](https://linux.die.net/man/1/ar);
+* [`bsdtar`](https://man.archlinux.org/man/bsdtar.1).
+
+### Extract contents
+
+- Extract the `.deb` contents:
+
+```bash
+ar xv {{latest_installer_deb}}
+```
+
+- Extract the `data.tar.zst` contents:
+
+```bash
+bsdtar -xvf data.tar.zst
+```
+
+The binary will be located at `./usr/local/bin/krux-installer`.
+
+## After install
+
+----8<----
+after-install-installer.en.txt
+----8<----
\ No newline at end of file
diff --git a/docs/getting-started/installing/from-gui/usage.en.md b/docs/getting-started/installing/from-gui/usage.en.md
new file mode 100644
index 0000000..f249ea3
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/usage.en.md
@@ -0,0 +1,254 @@
+This guide will walk through the basic use of the installer. At startup, it can differ in some
+operational systems. In the rest, the procedures will be similar.
+
+### Main Menu
+When executing the **Krux-Installer**, you will be presented with a menu of 4 enabled buttons and
+two disabled buttons:
+
+<img width="640" src="../../../../img/krux-installer/main.png" alt="Krux-Installer Main Menu" />
+
+* Enabled buttons:
+ * `Version`: select a firmware version;
+
+ * `Device`: select a supported device for the selected version;
+
+ * `Settings`: change some application settings;
+
+ * `About`: just show some information about the application.
+
+* Disabled buttons:
+
+ * `Flash firmware`: This button will start the flash firmware procedure;
+
+ * It will be enabled when user select **both** version and device;
+
+ * `Wipe device`: This button will start the wipe device procedure.
+
+ * It will be enabled when user select the device.
+
+#### Kivy Fatal Error - OpenGL
+Our latest version uses Kivy and requires at least OpenGL version 2.0, if you encounter this error, try installing the [OpenCL™, OpenGL®, and Vulkan® Compatibility Pack](https://apps.microsoft.com/detail/9nqpsl29bfff) from Microsoft.
+
+<img src="../../../../img/krux-installer/opengl-error.jpg" style="width: 37%; min-width: 250px;">
+
+### Select version
+
+At startup, the application will setup it to the latest one, `{{latest_krux}}`. But you can select
+even a beta release or older versions:
+
+<img width="640" src="../../../../img/krux-installer/select_version_menu.png" alt="Krux-Installer Select Version Menu" />
+
+* Click in the button that show the text `Version: {{latest_krux}}`;
+
+* To select a beta release, click on button that show the text `odudex/krux_binaries`;
+
+* To select an older version, click on button that show the text `Old versions`;
+
+#### Beta release
+
+After choose `odudex/krux_binaries`, you'll be warned with a message:
+
+<img width="640" src=" ../../../../img/krux-installer/warn_beta.png" alt="Krux-Installer warning beta version" />
+
+#### Older versions
+
+* We put this option in case you have any interest in the history of firmware development;
+
+<img width="640" src=" ../../../../img/krux-installer/select_old_version_menu.png" alt="Krux-Installer Select Old Version Menu" />
+
+* Each version supports one device or the other;
+
+* For example: the version `v22.03.0` has support only for `m5stickv`.
+
+
+### Settings
+
+**Krux-Installer** will give to you some freedom of choices for:
+
+* Krux-Installer settings;
+
+* General settings;
+
+#### Krux-Installer specific settings
+
+Here you can configure some of the specifics of krux firmare, like:
+
+<img width="640" src=" ../../../../img/krux-installer/app_settings.png" alt="Krux-Installer App settings Menu" />
+
+* Where you'll save downloaded assets;
+
+* The flash baudrate
+
+* The natural language that will be used in the application ([system locale](https://en.wikipedia.org/wiki/Locale_(computer_software))).
+
+##### Flash baudrate
+The flash baudrate is how quickly the firmware will be written to the device.
+
+<img width="640" src=" ../../../../img/krux-installer/baudrate.png" alt="Krux-Installer baudrate" />
+
+Use one of the following (m5StickV doesn't support 2000000): 9600, 19200, 28800, 38400, 57600, 76800, 115200,
+230400, 460800, 576000, 921600, 1500000, 2000000.
+
+##### System locale
+
+At startup, **Krux-Installer** recognize the locale used in your system. If your language isn't supported, it will defaults to `en_US`.
+
+<img width="640" src=" ../../../../img/krux-installer/locale_menu.png" alt="Krux-Installer locale menu" />
+
+
+### Select Device
+
+Everytime you select a new version, you'll see that the device button will be
+reseted to `Device: select a new one` state. Once a version is selected you can choose a device
+on which the firmware will be written.
+
+First, select the device we want to flash. After that the menu will shown three items:
+
+<img width="640" src=" ../../../../img/krux-installer/select_device.png" alt="Select Device Menu" />
+
+Note that some devices may be disabled if they are not supported by the chosen version
+
+### Flash device
+
+Once you choose the device and version, it enables the "flash device" button. It will start an
+**automatic** process of:
+
+* For official firmware's releases:
+
+ * Warning;
+
+ * Download;
+
+ * Verification:
+
+ * Unzip the correct firmware;
+
+ * Flash:
+
+ * The flash itself via USB;
+
+ * Air-gapped update via SD card;
+
+
+* For beta releases:
+
+ * Download asset;
+
+ * The flash itself;
+
+#### Warning
+
+If you already downloaded assets, you'll be warned about this and will be offered the possibility
+to download again or continue without downloading:
+
+<img width="640" src=" ../../../../img/krux-installer/warn_already_downloaded.png" alt="Krux-Installer already downloaded" />
+
+#### Download
+
+**Krux-Installer** download can download four assets for official releases or one for beta releases.
+
+##### Official releases
+
+* A `zip` file containing all firmwares for each device;
+
+* Download a `zip.sha256.txt` file containing a `zip`'s digital fingerprint;
+
+* Download a `zip.sig` file containing a `zip`'s digital signature;
+
+* Download the `selfcustody.pem` file containing a public key certificate, signed by `odudex`;
+
+<img width="640" src=" ../../../../img/krux-installer/download_assets.png" alt="Krux-Installer downloading assets" />
+
+##### Beta releases
+
+* A `kfpkg` file containing the specific firmware for choosen device;
+
+#### Verification
+
+* Integrity verification compares the computed hash of `zip` against thei provided `zip.sha256.txt`;
+
+* Authenticity verification check if the `zip` file was really signed by `odudex`, using
+the `zip.sig` and `selfcustody.pem`.
+
+<img width="640" src=" ../../../../img/krux-installer/verification.png" alt="Krux-Installer verification process" />
+
+
+#### Unzip
+
+Now you will be able to select if you do a flash process or need to do an airgap process:
+
+<img width="640" src=" ../../../../img/krux-installer/unzip.png" alt="Krux-Installer unzip" />
+
+Click on [Flash with](#flash-with) to install via USB or [Air-gapped update with](#air-gapped-update-with) to perform upgrades via an SD card.
+
+#### Flash with
+
+When flash starts, it will warn you to **not disconnect the device until the process is complete**.
+You'll be able to see the flash progress:
+
+<img width="640" src=" ../../../../img/krux-installer/flash.png" alt="Krux-Installer unzip" />
+> ⚠️ TIP: You must connect and turn on your device **before click extract and flashing starts!**.
+
+As well a done icon:
+
+<img width="640" src=" ../../../../img/krux-installer/flash_done.png" alt="Krux-Installer unzip" />
+
+> ⚠️ TIP:
+----8<----
+flash-krux-logo.en.txt
+----8<----
+
+
+##### Error flashing
+----8<----
+error-flashing-windows.en.txt
+----8<----
+
+
+
+#### Air-gapped update with
+
+Once you've installed the initial firmware on your device via USB, you can perform further firmware upgrades via SD card to keep the device airgapped.
+
+<img width="640" src=" ../../../../img/krux-installer/unzip.png" alt="Krux-Installer unzip" />
+> ⚠️ Click on "Air-gapped update with"
+
+Once the `firmware.bin` and `firmware.bin.sig` are extracted, you'll see a warning message.
+
+<img width="640" src=" ../../../../img/krux-installer/warn_airgap.png" alt="Krux-Installer warn airgap" />
+
+Insert the SD card and click 'Proceed' to allow the installer to detect it.
+
+<img width="640" src=" ../../../../img/krux-installer/list_drivers.png" alt="Krux-Installer warn airgap" />
+> ⚠️ If a single SD card is inserted, the screen will display a large button. If multiple removable drives are detected, both SD cards and other drives will be listed.
+
+Select the desired removable drive to copy both `firmware.bin` and `firmware.bin.sig.` The first is the Krux firmware, and the second is a signature file that verifies the firmware’s integrity and authenticity.
+
+Now you can compare the firmware's hash computed by installer with the firmware's hash computed by the device.
+
+<img width="640" src=" ../../../../img/krux-installer/airgap_done.png" alt="Krux-Installer warn airgap" />
+> ⚠️ Once files are copied, remove the SD card from computer, connect to device and compare the hashes
+
+### Wipe device
+
+This is a two step process, **Warning msg** and **Wipe process**.
+
+#### Warning
+
+Before the wipe starts, it will show to you a message:
+
+<img width="640" src=" ../../../../img/krux-installer/wipe_warn.png" alt="Wipe Warning" />
+> ⚠️ TIP: It's useful when your device is not working or for security reasons.
+To use Krux again, you'll need to re-flash the firmware.
+
+#### Wipe
+
+Once the process starts, the screen will appear frozen and a spinner will keep moving.
+When it's done, you can scroll down you will see a `check` icon.
+
+<img width="640" src=" ../../../../img/krux-installer/wipe.png" alt="Wipe Warning" />
+> ⚠️ TIP: Do not unplug or poweroff your device or computer. Wait until the process finishes.
+
+----8<----
+tips-after-install.en.txt
+----8<----
diff --git a/docs/getting-started/installing/from-gui/windows.en.md b/docs/getting-started/installing/from-gui/windows.en.md
new file mode 100644
index 0000000..40f6876
--- /dev/null
+++ b/docs/getting-started/installing/from-gui/windows.en.md
@@ -0,0 +1,80 @@
+# :material-microsoft-windows: Download assets
+
+* [`{{latest_installer_win}}`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_win}})
+* [`{{latest_installer_win}}.sha256.txt`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_win}}.sha256.txt)
+* [`{{latest_installer_win}}.sig`](https://github.com/selfcustody/krux-installer/releases/download/{{latest_installer}}/{{latest_installer_win}}.sig)
+
+## Verify the integrity
+
+----8<----
+verify-the-integrity-explain.en.txt
+----8<----
+
+```pwsh
+(Get-FileHash '.\{{latest_installer_win}}').Hash.ToLower() -eq (Get-Content '.\{{latest_installer_win}}.sha256.txt').split(" ")[0]
+```
+
+The result in prompt should be `True`.
+
+Alternatively, you can check more closely in two steps:
+
+* Compute the binary sha256sum hash:
+
+```pwsh
+# Option 1: Compute in default way
+Get-FileHash '.\{{latest_installer_win}}'
+
+# Option 2: Compute and filter the necessary information
+(Get-FileHash '.\{{latest_installer_win}}').Hash
+
+# Option 3: Compute, filter and process the Hash for lowercase letters
+(Get-FileHash '.\{{latest_installer_win}}').Hash.ToLower()
+```
+
+* Compare with provided hash:
+
+```pwsh
+# Option 1: Get content
+Get-Content '.\{{latest_installer_win}}.sha256.txt'
+
+# Option 2: Get content and filter the necessary information
+(Get-Content '.\{{latest_installer_win}}.sha256.txt').split(" ")[0]
+```
+
+## Verify the authenticity
+
+* You'll need have [GPG](https://gnupg.org/) installed;
+* We recommend installing [GPG4Win](https://www.gpg4win.org/).
+
+----8<----
+verify-the-signature-explain.en.txt
+----8<----
+
+```pwsh
+gpg --verify ./{{latest_installer_win}}.sig
+```
+
+----8<----
+verify-the-signature-tip.en.txt
+----8<----
+
+## Install
+
+Execute the `{{latest_installer_win}}`. You'll be faced with a blue window saying
+"Windows protected your PC". This occurs because we don't have a
+[code signing certificate](https://signmycode.com/resources/how-to-sign-an-exe-or-windows-application):
+
+<img width="450" src="../../../../img/krux-installer/windows_warn0.jpg" alt="Windows protected your computer" />
+
+----8<----
+verify-the-signature-trust-tip.en.txt
+----8<----
+
+Follow the installer's instructions to complete the installation. At the end, click on
+"Create desktop icon":
+
+## After install
+
+----8<----
+after-install-installer.en.txt
+----8<----
diff --git a/docs/getting-started/installing/from-pre-built-release.en.md b/docs/getting-started/installing/from-pre-built-release.en.md
new file mode 100644
index 0000000..306884a
--- /dev/null
+++ b/docs/getting-started/installing/from-pre-built-release.en.md
@@ -0,0 +1,91 @@
+This page explains how to download and install Krux firmware from our official, pre-built latest release.
+
+[<img src="../../../img/badge_github.png" width="186">](https://github.com/selfcustody/krux/releases)
+
+### Verify the files
+Before installing the release, it's a good idea to check that:
+
+1. The *SHA256 hash* of `{{latest_krux}}.zip` matches the hash in `{{latest_krux}}.zip.sha256.txt`
+2. The *signature file* `{{latest_krux}}.zip.sig` can be verified with the [`selfcustody.pem` public key](https://github.com/selfcustody/krux/blob/main/selfcustody.pem) found in the root of the krux repository.
+
+You can either do this manually or with the `krux` shell script, which contains helper commands for this:
+```bash
+### Using krux script ###
+# Hash checksum
+./krux sha256 {{latest_krux}}.zip
+# Signature
+./krux verify {{latest_krux}}.zip selfcustody.pem
+
+### Manually ###
+# Hash checksum
+sha256sum {{latest_krux}}.zip.sha256.txt -c
+#Signature
+openssl sha256 <{{latest_krux}}.zip -binary | openssl pkeyutl -verify -pubin -inkey selfcustody.pem -sigfile {{latest_krux}}.zip.sig
+```
+
+On Mac you may need to install `coreutils` to be able to use `sha256sum`
+```
+brew install coreutils
+```
+
+Fun fact: Each new Krux release is signed with Krux!
+
+### Flash the firmware onto the device
+Extract the latest version of Krux you downloaded and enter the folder:
+```bash
+unzip {{latest_krux}}.zip && cd {{latest_krux}}
+```
+
+Connect the device to your computer via USB (for Maix Amigo, make sure you’re using bottom port), power it on, and run the following, replacing `DEVICE` with either `m5stickv`, `amigo`, `bit`, `cube` or `yahboom` (to Yahboom you may need to manually specify the port, for example `/dev/ttyUSB0` on Linux or `COM6` on Windows):
+```bash
+./ktool -B goE -b 1500000 maixpy_DEVICE/kboot.kfpkg
+```
+
+For `dock` or `wonder_mv` use the `-B dan` parameter:
+```bash
+./ktool -B dan -b 1500000 maixpy_dock/kboot.kfpkg
+```
+
+----8<----
+flash-krux-logo.en.txt
+----8<----
+
+----8<----
+amigo-more-info-faq.en.txt
+----8<----
+
+#### Troubleshooting
+If `ktool` fails to run, you may need to give it executable permissions with `chmod +x ./ktool`, or you might need to use "sudo" if your user don't have access to serial port. In Windows or Mac you may need to explicitly allow the tool to run by adding an exception for it.
+
+If the flashing process fails midway through, check the connection, restart the device, and try the command again.
+
+Two serial ports are created when `Amigo` and `Bit` are connected to a PC. Sometimes Ktool will pick the wrong port and flashing will fail. Manually specify the serial port to overcome this issue using `-p` argument:
+
+##### Linux
+See the correct port using `ls /dev/ttyUSB*`, in the example below we use `/dev/ttyUSB0`:
+```bash
+./ktool-linux -B goE -b 1500000 maixpy_amigo/kboot.kfpkg -p /dev/ttyUSB1
+```
+
+##### Windows
+See the correct port at **Device Manager -> Ports (COM & LPT)**, in the example below we use `COM6`:
+```pwsh
+.\ktool-win.exe -B goE -b 1500000 maixpy_amigo\kboot.kfpkg -p COM6
+```
+
+##### Mac
+Remove the Gatekeeper quarantine extended attribute from ktool-mac:
+```bash
+xattr -d com.apple.quarantine ktool-mac
+```
+
+See the correct port using the command line: `ls /dev/cu.usbserial*`, in the example below we use `/dev/cu.usbserial-10` (If the output isn't what you expect try a different cable, preferably a smartphone usb-c charger cable):
+```bash
+./ktool-mac -B goE -b 1500000 maixpy_amigo/kboot.kfpkg -p /dev/cu.usbserial-10
+```
+
+Different OS versions may have different port names, and the absence of ports may indicate a connection, driver or hardware related issue. See [Troubleshooting](../../troubleshooting.md/#device-not-charging-or-being-recognized) for more info.
+
+----8<----
+tips-after-install.en.txt
+----8<----
diff --git a/docs/getting-started/installing/from-source.en.md b/docs/getting-started/installing/from-source.en.md
new file mode 100644
index 0000000..1b8a666
--- /dev/null
+++ b/docs/getting-started/installing/from-source.en.md
@@ -0,0 +1,109 @@
+This page explains how to install Krux from source. You can check a simplified version of these instructions in our [README](https://github.com/selfcustody/krux) too.
+
+### Fetch the code
+This will download the source code of Krux as well as the code of all its dependencies inside a new folder called `krux` (needs [`git`](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)):
+```bash
+git clone --recurse-submodules https://github.com/selfcustody/krux
+```
+
+**Note**: When you wish to pull updates (to all submodules, their submodules, ...) to this repo, use:
+```bash
+git pull origin main && git submodule update --init --recursive
+```
+
+#### Prerequisite for upgrading via microSD
+If you wish to perform airgapped upgrades via microSD card later, you will need to have a private and public key pair to sign your builds and verify the signatures. If you do not want to perform further airgapped upgrades, jump to [build section](#build-the-firmware-linux-or-wsl).
+
+You can use an existing Krux installation and mnemonic to sign your builds with, **or** you can generate a keypair and sign from the [`openssl` CLI](https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations). Commands have been added to the `krux` shell script to make this easier.
+
+In either case, you will need to update the `SIGNER_PUBKEY` field in `src/krux/metadata.py` to store your public key so that Krux can verify future builds before installing.
+
+To generate a keypair:
+```bash
+./krux generate-keypair
+./krux pem-to-pubkey pubkey.pem
+```
+
+The first command will create `privkey.pem` and `pubkey.pem` files you can use with openssl, and the second command will output your public key in the form expected by Krux.
+
+Once you've updated the `SIGNER_PUBKEY` with this value, you can proceed with the regular build process.
+
+### Build the firmware (Linux or WSL)
+The [krux bash script](https://github.com/selfcustody/krux/blob/main/krux) contains commands for common development tasks. It assumes a Linux host, you will need to have [Docker Desktop or Docker Engine](https://docs.docker.com/desktop/), `openssl`, and `wget` installed at a minimum for the commands to work as expected. It works on Windows using WSL. The channel Crypto Guide from Youtube made a step-by-step video - [Krux DIY Bitcoin Signer: Build From Source & Verify (With Windows + WSL2 + Docker)](https://www.youtube.com/watch?v=Vmr_TFy2TfQ)
+
+To build and flash the firmware:
+```bash
+# build firmware for Maix Amigo
+./krux build maixpy_amigo
+```
+
+The first time, the build can take around an hour or so to complete. Subsequent builds should take only a few minutes. If all goes well, you should see a new `build` folder containing `firmware.bin` and `kboot.kfpkg` files when the build completes.
+
+**Note**: if you encounter any of these errors while building, it is a problem connecting to github, try again (if the error persists, try changing the DNS/VPN or correcting the hostname resolution of github.com to an IP that is working for you):
+```
+error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err8)
+fatal: the remote end hung up unexpectedly
+fatal: early EOF
+fatal: index-pack failed
+fatal: clone of ... failed
+Failed to clone ...
+```
+
+#### Reproducibility
+If you build from the `main` branch of the source code, you should be able to reproduce the build process used to generate the latest release binaries and obtain exactly the same copies of the `firmware.bin` and `kboot.kfpkg` files, with matching hash checksums (to check for an older version, use the `tag` instead).
+
+To check, use the compiled files for the target device. Each command should output the same hash for the two provided files:
+```bash
+sha256sum build/firmware.bin {{latest_krux}}/maixpy_DEVICE/firmware.bin
+sha256sum build/kboot.kfpkg {{latest_krux}}/maixpy_DEVICE/kboot.kfpkg
+```
+
+If you want to extract and verify the `firmware.bin`file contained in `kboot.kfpkg`, use the following:
+
+```bash
+unzip kboot.kfpkg -d ./kboot/
+```
+
+### Flash the firmware onto the device
+Connect the device to your computer via USB (for Maix Amigo, make sure you’re using bottom port), power it on, and run the following, replacing `DEVICE` with either `m5stickv`, `amigo`, `bit`, `cube`, `dock`, `yahboom` or `wonder_mv`:
+```bash
+# flash firmware to DEVICE
+./krux flash maixpy_DEVICE
+```
+If flashing fails try reading [Troubleshooting](../../troubleshooting.md)
+
+----8<----
+flash-krux-logo.en.txt
+----8<----
+
+----8<----
+amigo-more-info-faq.en.txt
+----8<----
+
+### Signing the firmware
+You can sign the firmware to [perform airgapped upgrades](#prerequisite-for-upgrading-via-microsd) using one of the two methods listed below:
+
+#### Method 1: Signing from Krux
+First, calculate the SHA256 hash of the new firmware by running:
+```bash
+./krux sha256 build/firmware.bin
+```
+
+Copy this hex string and turn it into a QR code using whichever QR code generator you'd like.
+
+In Krux, enter the mnemonic of your private key that will be used for signing, and go to **Sign -> Message**. Scan the QR code you generated, and you will be asked if you wish to sign the hash. Proceed, and you will be presented with a base64-encoded string containing the signature, as text and as a QR code.
+
+Take this string and create a signature file by running:
+```bash
+./krux b64decode "signature-in-base64" > build/firmware.bin.sig
+```
+
+This will generate a `firmware.bin.sig` file containing a signature of the firmware's SHA256 hash.
+
+#### Method 2: Signing from your computer with OpenSSL
+With the keypair [you generated before](#prerequisite-for-upgrading-via-microsd), you can now run:
+```bash
+./krux sign build/firmware.bin privkey.pem
+```
+
+This will generate a `firmware.bin.sig` file containing a signature of the firmware's SHA256 hash.
diff --git a/docs/getting-started/installing/from-test-release.en.md b/docs/getting-started/installing/from-test-release.en.md
new file mode 100644
index 0000000..f874b62
--- /dev/null
+++ b/docs/getting-started/installing/from-test-release.en.md
@@ -0,0 +1,144 @@
+This page explains how to install Krux from a test (beta), pre-built release.
+
+### Warning
+Keep in mind that these are unsigned binaries.
+
+### Download
+Download experimental compiled firmware at [test (beta) repository](https://github.com/odudex/krux_binaries) or the Mobile Android app `apk` at [KruxMobileApp](https://github.com/selfcustody/KruxMobileApp).
+
+#### Mobile - Android
+The [Krux Mobile Android app](../../faq.md#what-is-krux-mobile-android-app) is designed for learning about Krux and Bitcoin air-gapped transactions. Due to the numerous potential vulnerabilities inherent in smartphones, such as the lack of control over the operating system, libraries, and hardware peripherals, the Krux app should NOT be used to manage wallets containing savings or important keys and mnemonics. For secure management of your keys, a dedicated device is recommended.
+
+#### Compiled firmware for Kendryte K210 devices
+#### M5StickV
+To Flash M5StickV run the following.
+
+##### Linux
+```bash
+./ktool-linux -B goE -b 1500000 maixpy_m5stickv/kboot.kfpkg
+```
+
+##### Mac
+```bash
+./ktool-mac -B goE -b 1500000 maixpy_m5stickv/kboot.kfpkg
+```
+
+##### Windows
+```pwsh
+.\ktool-win.exe -B goE -b 1500000 maixpy_m5stickv\kboot.kfpkg
+```
+
+#### Sipeed Maix Amigo
+To Flash Maix Amigo run the following.
+
+##### Linux
+```bash
+./ktool-linux -B goE -b 1500000 maixpy_amigo/kboot.kfpkg
+```
+
+##### Mac
+```bash
+./ktool-mac -B goE -b 1500000 maixpy_amigo/kboot.kfpkg
+```
+
+##### Windows
+```pwsh
+.\ktool-win.exe -B goE -b 1500000 maixpy_amigo\kboot.kfpkg
+```
+
+----8<----
+amigo-more-info-faq.en.txt
+----8<----
+
+#### Sipeed Maix Bit
+To Flash Maix Bit run the following.
+
+##### Linux
+```bash
+./ktool-linux -B goE -b 1500000 maixpy_bit/kboot.kfpkg
+```
+
+##### Mac
+```bash
+./ktool-mac -B goE -b 1500000 maixpy_bit/kboot.kfpkg
+```
+
+##### Windows
+```pwsh
+.\ktool-win.exe -B goE -b 1500000 maixpy_bit\kboot.kfpkg
+```
+
+#### Sipeed Maix Cube
+To Flash Maix Cube run the following.
+
+##### Linux
+```bash
+./ktool-linux -B goE -b 1500000 maixpy_cube/kboot.kfpkg
+```
+
+##### Mac
+```bash
+./ktool-mac -B goE -b 1500000 maixpy_cube/kboot.kfpkg
+```
+
+##### Windows
+```pwsh
+.\ktool-win.exe -B goE -b 1500000 maixpy_cube\kboot.kfpkg
+```
+
+#### Sipeed Maix Dock
+To Flash Maix Dock you need to pass the `-B dan` parameter.
+
+##### Linux
+```bash
+./ktool-linux -B dan -b 1500000 maixpy_dock/kboot.kfpkg
+```
+
+##### Mac
+```bash
+./ktool-mac -B dan -b 1500000 maixpy_dock/kboot.kfpkg
+```
+
+##### Windows
+```pwsh
+.\ktool-win.exe -B dan -b 1500000 maixpy_dock\kboot.kfpkg
+```
+
+#### Aimotion Yahboom k210 module
+To Flash Yahboom k210 module you'll have to manually specify the port.
+
+##### Linux
+See the correct port using `ls /dev/ttyUSB*`, in the example below we use `/dev/ttyUSB0`:
+```bash
+./ktool-linux -B goE -b 1500000 -p /dev/ttyUSB0 maixpy_yahboom/kboot.kfpkg
+```
+
+##### Mac
+See the correct port using the command line: `ls /dev/cu.usbserial*`, in the example below we use `/dev/cu.usbserial-10`:
+```bash
+./ktool-mac -B goE -b 1500000 -p /dev/cu.usbserial-10 maixpy_yahboom/kboot.kfpkg
+```
+
+##### Windows
+See the correct port at **Device Manager -> Ports (COM & LPT)**, in the example below we use `COM6`:
+```pwsh
+.\ktool-win.exe -B goE -b 1500000 -p COM6 maixpy_yahboom\kboot.kfpkg
+```
+
+#### Hiwonder WonderMV Vision Recognition Module
+To Flash WonderMV you need to pass the `-B dan` parameter.
+
+##### Linux
+```bash
+./ktool-linux -B dan -b 1500000 maixpy_wonder_mv/kboot.kfpkg
+```
+
+##### Mac
+```bash
+./ktool-mac -B dan -b 1500000 maixpy_wonder_mv/kboot.kfpkg
+```
+
+##### Windows
+```pwsh
+.\ktool-win.exe -B dan -b 1500000 maixpy_wonder_mv\kboot.kfpkg
+```
diff --git a/docs/getting-started/installing/index.en.md b/docs/getting-started/installing/index.en.md
new file mode 100644
index 0000000..6e5d4a7
--- /dev/null
+++ b/docs/getting-started/installing/index.en.md
@@ -0,0 +1,11 @@
+You can install Krux in four different ways:
+
+- [:material-package-variant: Using Krux-Installer GUI application](../installing/from-gui/index.md)
+- [:material-console: From pre-built official release](../installing/from-pre-built-release.md)
+- [:material-console: From pre-built test (beta) release](../installing/from-test-release.md)
+- [:material-console: From source](../installing/from-source.md)
+
+### Requirements
+Please, check the [parts list](../../parts.md) for the compatible devices and requirements.
+
+After the first firmware install, you can use a microSD card if you wish to perform further [airgapped updates](../features/sd-card-update.md).
diff --git a/docs/getting-started/navigation.en.md b/docs/getting-started/navigation.en.md
new file mode 100644
index 0000000..ffab700
--- /dev/null
+++ b/docs/getting-started/navigation.en.md
@@ -0,0 +1,7 @@
+Below is the mind map representation of the currently menus available. Click the circle with a number (Ex.: :material-numeric-3-circle-outline:) to the right of each node to expand and explore. Also, enable full screen in the top right menu for better viewing :wink:.
+
+### Login Menu
+<iframe width="1000" height="800" src="https://gitmind.com/app/docs/m1jf65sy"; allowfullscreen></iframe>
+
+### Home Menu (Loaded a mnemonic)
+<iframe width="1000" height="800" src="https://gitmind.com/app/docs/mfo6gdol"; allowfullscreen></iframe>
diff --git a/docs/getting-started/settings.en.md b/docs/getting-started/settings.en.md
new file mode 100644
index 0000000..fecb412
--- /dev/null
+++ b/docs/getting-started/settings.en.md
@@ -0,0 +1,229 @@
+In Krux first menu, there is a `Settings` entry. Some submenu entries have too many options to fit on a single screen, swipe up :material-gesture-swipe-up: or down :material-gesture-swipe-down: to navigate between the screens - if your device has a touchscreen. Below is a breakdown of the options you can change:
+
+<img src="../../img/maixpy_amigo/settings-options-300.png" class="amigo">
+<img src="../../img/maixpy_m5stickv/settings-options-250.png" class="m5stickv">
+
+### Default Wallet
+
+Set the default attributes for wallet loading.
+
+#### Network
+<img src="../../img/maixpy_m5stickv/network-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/network-options-300.png" align="right" class="amigo">
+
+This option allows you to switch between `mainnet` (the default) and `testnet`. `Testnet` can be used to try out different wallet coordinators or for development.
+
+<div style="clear: both"></div>
+
+#### Policy Type
+<img src="../../img/maixpy_m5stickv/policy-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/policy-options-300.png" align="right" class="amigo">
+
+Choose between `Single-sig`, `Multisig`, or `Miniscript` to avoid having to customize the policy type every time you load a key.
+
+<div style="clear: both"></div>
+
+#### Script Type
+<img src="../../img/maixpy_m5stickv/script-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/script-options-300.png" align="right" class="amigo">
+
+As with `Policy Type`, pre-select the most commonly used script type so that you don't have to change it every time you load a wallet. Your options are `Native Segwit`, `Neste Segwit`, `Taproot (Experimental)`, and `Legacy`. If you choose a script type that isn’t implemented for the selected policy type—such as a `Legacy` script for `Miniscript`—the system will default to `Native Segwit`.
+
+**Note**: These settings do not restrict further changes to these wallet attributes, they just set their default values.
+
+<div style="clear: both"></div>
+
+### Encryption
+<img src="../../img/maixpy_m5stickv/encryption-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/encryption-options-300.png" align="right" class="amigo">
+
+Modify the encryption method and parameters to fit your needs. This will be used when storing encrypted mnemonics or creating encrypted QR codes. For more info see [Krux Encryption - Regarding BIP39 Mnemonics](features/encryption/encryption.md/#regarding-bip39-mnemonics).
+
+<div style="clear: both"></div>
+
+#### PBKDF2 Iter. (Iterations)
+<img src="../../img/maixpy_m5stickv/encryption-options-pbkdf2-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/encryption-options-pbkdf2-300.png" align="right" class="amigo">
+
+When you enter the encryption key, it is not directly used to encrypt your data. In order to protect against brute force attacks, the key is derived multiple times using hashing functions. PBKDF2 (Password-Based Key Derivation Function) iterations stands for the amount of derivations that will be performed over your key prior to encrypt/decrypt your mnemonic.
+
+**Note**: Increasing this value will make the encryption harder, at the cost of taking longer to encrypt/decrypt your mnemonics. Values must be multiple of 10,000 (to save data space on QR codes).
+
+<div style="clear: both"></div>
+
+#### Encryption Mode
+<img src="../../img/maixpy_m5stickv/encryption-options-mode-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/encryption-options-mode-300.png" align="right" class="amigo">
+
+Choose between well known and widely used AES (Advanced Encryption Standard) modes:
+
+##### AES-ECB
+ECB (Electronic Codebook) is a simpler method where data blocks are encrypted individually. Compared to CBC, it will be faster and simpler to encrypt, QR codes will have a lower density and will be easier to [transcribe](features/QR-transcript-tools.md).
+
+##### AES-CBC
+CBC (Cipher-block Chaining) is considered more secure than ECB. The first data block, an initialization vector (IV), is used to add random data to the encryption. The encryption of subsequent blocks depends on the data from previous blocks, ensuring chaining.
+
+Encryption will take longer because a snapshot will be needed to generate the IV. This IV will be stored together with the encrypted data, making encrypted QR codes denser and harder to [transcribe](features/QR-transcript-tools.md).
+
+<div style="clear: both"></div>
+
+### Hardware
+<img src="../../img/maixpy_m5stickv/settings-options-hardware-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-options-hardware-300.png" align="right" class="amigo">
+
+Customize the parameters available for your device and change printer settings.
+
+<div style="clear: both"></div>
+
+#### Buttons
+<img src="../../img/maixpy_m5stickv/settings-btn-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-btn-300.png" align="right" class="amigo">
+
+You can change the debounce threshold in milliseconds. With lower values, faster movements and navigation will be allowed.
+
+The caveat is low values can cause issues, such as double click and unexpected movements, especially with lower quality buttons or encoders. If this is the case increase the value to make navigation more stable.
+
+<div style="clear: both"></div>
+
+#### Display
+<img src="../../img/maixpy_m5stickv/settings-options-hardware-display-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-options-hardware-display-300.png" align="right" class="amigo">
+
+Available display settings vary based on your device. Amigo has several options detailed below, Yahboom and WonderMV have an option for flipped orientation, others will have brightness control and Dock does not have this submenu.
+
+Few Maix Amigo screens are different, here you can customize the `BGR Colors`, `Flipped X Coordinates`, `Inverted Colors` and `LCD Type`. For more info see [Troubleshooting](../troubleshooting.md/#troubleshooting-lcd-settings-on-maix-amigo)
+
+<div style="clear: both"></div>
+
+### Printer
+<img src="../../img/maixpy_m5stickv/printer-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/printer-options-300.png" align="right" class="amigo">
+
+You can set up a TTL serial thermal printer or GRBL. It is also possible to store a GRBL g-code CNC instructions file on an SD card to engrave QR codes.
+
+#### CNC
+Define several machining parameters according to the desired size, material you'll use, and your CNC characteristics and capabilities. See [CNC Engraving](features/printing/cnc.md) for more details.
+
+#### Thermal
+Printers can come with different baudrates from the manufacturer. By default, Krux assumes the connected printer will have a baudrate of `9600`. If yours is different, you can change it here.
+
+Also setup the TX Pin you'll use (i.e., 35 on M5StickV, 7 on Maix Amigo, 8 on Yahboom, 25 on Cube, 28 on WonderMV) and tweak other parameters according to your printer recommendations. For most printers you will only need to connect 2 cables, the device TX to the printer RX and ground. Current uses of printing are listed [here](features/printing/printing.md). Consult the [parts list](../parts.md/#optional-ttl-serial-thermal-printer) for supported printers.
+
+<div style="clear: both"></div>
+
+#### Driver
+<img src="../../img/maixpy_m5stickv/settings-printer-driver-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-printer-driver-300.png" align="right" class="amigo">
+
+Here you choose between `thermal/adafruit`, `cnc/file`, `cnc/grbl` or `none` (default). Leave this setting to `none` if you won't use a printer and don't want to be bothered by print prompts.
+
+<div style="clear: both"></div>
+
+#### Touchscreen (Maix Amigo, Yahboom and WonderMV only)
+<img src="../../img/maixpy_amigo/touchscreen-300.png" align="right" class="amigo">
+
+If your device has touchscreen you can change the touch detection threshold. If it is being too sensitive or detecting false or ghost touches, you should increase the threshold value, making it less sensitive. The other way is also valid, reduce the threshold to make the screen more sensitive to touches.
+
+**Tip**: If your Amigo or WonderMV's touchscreen is not working properly, you can disable it by turning on the device with your finger pressing the screen. This will allow you to operate the device using buttons only.
+
+<div style="clear: both"></div>
+
+### Language - Locale
+<img src="../../img/maixpy_m5stickv/locale-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/locale-options-300.png" align="right" class="amigo">
+
+Here you can change Krux to your language.
+
+<div style="clear: both"></div>
+
+### Persist
+<img src="../../img/maixpy_m5stickv/persist-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/persist-options-300.png" align="right" class="amigo">
+
+Choose between `flash` (device's internal memory) or `SD card` for the place where your settings changes will be stored (default values are not persisted).
+
+<div style="clear: both"></div>
+
+### Security
+<img src="../../img/maixpy_m5stickv/security-options-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/security-options-300.png" align="right" class="amigo">
+
+Adjust settings that may impact your security protocols.
+
+#### Shutdown Time
+Set the time it takes for Krux to automatically shut down. This feature not only conserves your device's battery, if it has one, but also serves as an important security measure. If you forget your device with private keys loaded, it will shut down automatically after the set time.
+
+**Note**: Devices without batteries and power management will not shut down but reboot, which will also unload keys.
+
+<div style="clear: both"></div>
+
+#### TC Flash Hash at Boot
+<img src="../../img/maixpy_m5stickv/settings-tc-boot-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-tc-boot-300.png" align="right" class="amigo">
+
+Chose if you would like to run [Tamper Check Flash Hash](features/tamper-detection.md) every time the device is powered on.
+
+Activating *TC Flash Hash* at boot helps prevent unauthorized use by requiring the *TC Code*. But is important to note, unlike a PIN, the *TC Code* does not provide access control over USB. This means that the device's memory remains accessible via USB, allowing it to be flashed with firmware that does not require the *TC Code*.
+
+<div style="clear: both"></div>
+
+#### Hide Mnemonics
+<img src="../../img/maixpy_m5stickv/settings-hide-mnemonic-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-hide-mnemonic-300.png" align="right" class="amigo">
+
+When `True`, Krux will disable the [New Mnemonic](./usage/generating-a-mnemonic.md) menu and hide the words when [Loading a Mnemonic](./usage/loading-a-mnemonic.md). It will also hide the words when using [BIP85 to create a BIP39 Mnemonic](./usage/navigating-the-main-menu.md#bip85) and disable the [Backup Mnemonic](./usage/navigating-the-main-menu.md#backup-mnemonic) menu.
+
+<div style="clear: both"></div>
+
+#### Tamper Check Code
+<img src="../../img/maixpy_m5stickv/tamper_check_settings-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/tamper_check_settings-300.png" align="right" class="amigo">
+
+Create or modify a Tamper Check Code. This code will be required every time [Tamper Check Flash Hash](features/tamper-detection.md) is executed.
+
+After creating the code, you will be prompted to fill the empty memory spaces with random entropy from the camera. This step is important to make *TC Flash Hash* more resilient to data manipulation by eliminating empty memory spaces that could be exploited in a sophisticated tamper attempt.
+
+The filling process requires good entropy images. If, for any reason, such as starting the process in a dark room, you fail to capture good entropy images, you can restart the filling process by resetting your *TC Code*.
+
+The *TC Code* will be deleted if the device is wiped or user data is erased, which will consequently disable *TC Flash Hash*.
+
+<div style="clear: both"></div>
+
+### Appearance
+<img src="../../img/maixpy_m5stickv/settings-options-appearance-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-options-appearance-300.png" align="right" class="amigo">
+
+Configure `screensaver time` and change Krux to your desired `theme`.
+
+<div style="clear: both"></div>
+
+#### Screensaver time
+<img src="../../img/maixpy_m5stickv/settings-options-appearance-screensaver-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-options-appearance-screensaver-300.png" align="right" class="amigo">
+
+Set how long to wait idle before the screensaver appears. Enter 0 to disable the screensaver.
+
+<div style="clear: both"></div>
+
+#### Theme
+Choose your color theme according to your preference. Some themes may be more suitable for some devices, coordinator cameras and environments. As an example, it may be easier to scan QR codes from Krux devices using light theme in brighter environments.
+
+<img src="../../img/maixpy_amigo/theme-1-300.png" class="amigo">
+<img src="../../img/maixpy_amigo/theme-2-300.png" class="amigo">
+<img src="../../img/maixpy_amigo/theme-3-300.png" class="amigo">
+<img src="../../img/maixpy_amigo/theme-4-300.png" class="amigo">
+<img src="../../img/maixpy_amigo/theme-5-300.png" class="amigo">
+
+<img src="../../img/maixpy_m5stickv/theme-1-250.png" class="m5stickv">
+<img src="../../img/maixpy_m5stickv/theme-2-250.png" class="m5stickv">
+<img src="../../img/maixpy_m5stickv/theme-3-250.png" class="m5stickv">
+<img src="../../img/maixpy_m5stickv/theme-4-250.png" class="m5stickv">
+<img src="../../img/maixpy_m5stickv/theme-5-250.png" class="m5stickv">
+
+### Factory Settings
+<img src="../../img/maixpy_m5stickv/settings-options-factory-settings-250.png" align="right" class="m5stickv">
+<img src="../../img/maixpy_amigo/settings-options-factory-settings-300.png" align="right" class="amigo">
+
+Restore device to factory settings and reboot.
+
+<div style="clear: both"></div>
diff --git a/docs/getting-started/templates/Krux_Binary_Grid_double_clean_rev1.png b/docs/getting-started/templates/Krux_Binary_Grid_double_clean_rev1.png
new file mode 100644
index 0000000..aeb1b3f
Binary files /dev/null and b/docs/getting-started/templates/Krux_Binary_Grid_double_clean_rev1.png differ
diff --git a/docs/getting-started/templates/Krux_Binary_Grid_double_clean_rev1.svg b/docs/getting-started/templates/Krux_Binary_Grid_double_clean_rev1.svg
new file mode 100644
index 0000000..fb07a4f
--- /dev/null
+++ b/docs/getting-started/templates/Krux_Binary_Grid_double_clean_rev1.svg
@@ -0,0 +1,486 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="370mm"
+ height="200mm"
+ viewBox="0 0 370 200"
+ version="1.1"
+ id="svg1"
+ inkscape:version="1.4 (1:1.4+202410161351+e7c3feb100)"
+ sodipodi:docname="Krux_B_Grid-double_clean_rev1.svg"
+ inkscape:export-filename="Krux_B_Grid-double_rev1.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview1"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="mm"
+ inkscape:zoom="0.32516492"
+ inkscape:cx="561.25366"
+ inkscape:cy="315.22466"
+ inkscape:window-width="1374"
+ inkscape:window-height="831"
+ inkscape:window-x="66"
+ inkscape:window-y="32"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g64" />
+ <defs
+ id="defs1" />
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.92783"
+ id="rect14"
+ width="370"
+ height="200"
+ x="0"
+ y="0" />
+ <g
+ aria-label=" ██ ██ ██ ██████ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ "
+ id="text236"
+ style="font-weight:bold;font-size:9.87778px;line-height:0.94;-inkscape-font-specification:'sans-serif Bold';text-align:center;letter-spacing:0px;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke-width:1.521"
+ transform="matrix(1.5919149,0,0,1.6145418,237.44563,-70.224421)" />
+ <g
+ id="g26"
+ transform="translate(0,-7.65275)">
+ <g
+ id="g14"
+ transform="translate(30.245871,37.898621)">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.491743;stroke-opacity:1"
+ id="rect1"
+ width="140"
+ height="140"
+ x="-0.24587101"
+ y="-0.24587101"
+ ry="9.7564411" />
+ <g
+ id="g13">
+ <g
+ id="g1">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
+ d="M 9.9999995,10 V 130"
+ id="path146"
+ inkscape:tile-cx="9.9999993"
+ inkscape:tile-cy="69.999998"
+ inkscape:tile-w="0.49999999"
+ inkscape:tile-h="120"
+ inkscape:tile-x0="9.7499993"
+ inkscape:tile-y0="9.9999998" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(9.9999998)"
+ id="use269" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(20)"
+ id="use270" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(29.999999)"
+ id="use271" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(39.999999)"
+ id="use272" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(49.999999)"
+ id="use273" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(59.999999)"
+ id="use274" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(69.999998)"
+ id="use275" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(79.999998)"
+ id="use276" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(89.999998)"
+ id="use277" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(99.999998)"
+ id="use278" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(110)"
+ id="use279" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(120)"
+ id="use280" />
+ </g>
+ <g
+ id="g12"
+ transform="rotate(90,70,70)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
+ d="M 9.9999995,10 V 130"
+ id="path1"
+ inkscape:tile-cx="9.9999993"
+ inkscape:tile-cy="69.999998"
+ inkscape:tile-w="0.49999999"
+ inkscape:tile-h="120"
+ inkscape:tile-x0="9.7499993"
+ inkscape:tile-y0="9.9999998" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(9.9999998)"
+ id="use1" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(20)"
+ id="use2" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(29.999999)"
+ id="use3" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(39.999999)"
+ id="use4" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(49.999999)"
+ id="use5" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(59.999999)"
+ id="use6" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(69.999998)"
+ id="use7" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(79.999998)"
+ id="use8" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(89.999998)"
+ id="use9" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(99.999998)"
+ id="use10" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(110)"
+ id="use11" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(120)"
+ id="use12" />
+ </g>
+ </g>
+ </g>
+ </g>
+ <g
+ id="g64"
+ transform="translate(170,-7.65275)">
+ <g
+ id="g51"
+ transform="translate(30.245871,37.898621)">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.491743;stroke-opacity:1"
+ id="rect26"
+ width="140"
+ height="140"
+ x="-0.24587101"
+ y="-0.24587101"
+ ry="9.7564411" />
+ <g
+ id="g50">
+ <g
+ id="g37">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
+ d="M 9.9999995,10 V 130"
+ id="path26"
+ inkscape:tile-cx="9.9999993"
+ inkscape:tile-cy="69.999998"
+ inkscape:tile-w="0.49999999"
+ inkscape:tile-h="120"
+ inkscape:tile-x0="9.7499993"
+ inkscape:tile-y0="9.9999998" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(9.9999998)"
+ id="use26" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(20)"
+ id="use27" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(29.999999)"
+ id="use28" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(39.999999)"
+ id="use29" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(49.999999)"
+ id="use30" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(59.999999)"
+ id="use31" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(69.999998)"
+ id="use32" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(79.999998)"
+ id="use33" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(89.999998)"
+ id="use34" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(99.999998)"
+ id="use35" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(110)"
+ id="use36" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(120)"
+ id="use37" />
+ </g>
+ <g
+ id="g49"
+ transform="rotate(90,70,70)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
+ d="M 9.9999995,10 V 130"
+ id="path37"
+ inkscape:tile-cx="9.9999993"
+ inkscape:tile-cy="69.999998"
+ inkscape:tile-w="0.49999999"
+ inkscape:tile-h="120"
+ inkscape:tile-x0="9.7499993"
+ inkscape:tile-y0="9.9999998" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(9.9999998)"
+ id="use38" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(20)"
+ id="use39" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(29.999999)"
+ id="use40" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(39.999999)"
+ id="use41" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(49.999999)"
+ id="use42" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(59.999999)"
+ id="use43" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(69.999998)"
+ id="use44" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(79.999998)"
+ id="use45" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(89.999998)"
+ id="use46" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(99.999998)"
+ id="use47" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(110)"
+ id="use48" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#path146"
+ xlink:href="#path146"
+ transform="translate(120)"
+ id="use49" />
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/docs/getting-started/templates/Krux_Binary_Grid_double_rev1.png b/docs/getting-started/templates/Krux_Binary_Grid_double_rev1.png
new file mode 100644
index 0000000..e190796
Binary files /dev/null and b/docs/getting-started/templates/Krux_Binary_Grid_double_rev1.png differ
diff --git a/docs/getting-started/templates/Krux_Binary_Grid_double_rev1.svg b/docs/getting-started/templates/Krux_Binary_Grid_double_rev1.svg
new file mode 100644
index 0000000..26059eb
--- /dev/null
+++ b/docs/getting-started/templates/Krux_Binary_Grid_double_rev1.svg
@@ -0,0 +1,665 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="370mm"
+ height="200mm"
+ viewBox="0 0 370 200"
+ version="1.1"
+ id="svg1"
+ inkscape:version="1.4 (1:1.4+202410161351+e7c3feb100)"
+ sodipodi:docname="Krux_B_Grid-double_rev1.svg"
+ inkscape:export-filename="Krux_B_Grid-double_rev1.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview1"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="mm"
+ inkscape:zoom="0.32516492"
+ inksWhy this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.